是否可以在没有@Embeddable的情况下将JPA/Hibernate实体字段映射到另一个类中的字段



我有一个非常简单的实体(Person.java(,我想通过JPA/Hibernate持久化它。实体包含两个字段:ID和标识字符串。

ID是一个简单的Integer,没有问题。Identification String目前是一个String,但由于各种原因,我想使用String的包装类(IDString(,其中有各种验证方法。

我想知道在数据库中持久化Person表时,如何让JPA/Hibernate使用包装字符串(在自定义类IDString中(。我知道这可能可以通过让IDString是@Embeddable来解决,然后用@Embedded将IDString嵌入Person实体中,但我正在寻找另一种方法,主要是因为IDString在一个完全不同的包中,我不愿意去那里更改东西。

在谷歌上搜索,我发现https://www.baeldung.com/hibernate-custom-types,但它似乎主要是关于更复杂的情况,在这种情况下,你想将一个类转换为另一种类型,我确实觉得可能有一种更聪明的方法,我只是忽略了它。

这是实体(理论上(

@Entity(name="Person")
@Table(name="DB_TABLE_PERSON")
public class Person implements Serializable {
@Id
Integer id;
// WHAT SHOULD I PUT HERE? I WANT TO SIMPLY USE THE STRING INSIDE IDSTRING AS THE FIELD TO PERSIST
IDString idString;
// getter and setter for ID.

public void getIdString() {
return idString.getValue();
}
public void setIdString(String in) {
idString.setValue(in);
}
}

这是类IDString(理论上(:

public class IDString {
// I really want to be a POJO
private final String the_string;
public IdString(String input) {
if (isValid(input)) {
the_string = input;
} else {
throw new SomeCoolException("Invalid format of the ID String");
}
public boolean isValid(String input) {
// bunch of code to validate the input string
}
public String getValue() {
return the_string;
}
public void setValue(String input) {
if (isValid(input)) the_string = s;
else throw new SomeCoolException("Invalid format of the ID String");
}

我知道如果IDString在Entity中,我可以放置验证,但IDString将在其他地方使用(它是一个通用的自定义类(,所以我不想这样做。有简单的方法吗?

@Converter(autoApply=true) // autoApply is reasonable, if not use @Converter on field
public class IDStringConverter implements AttributeConverter<IDString,String> {
@Override
public String convertToDatabaseColumn(IDString attribute) {
return attribute != null ? attribute.getValue() : null;
}
@Override
public IDString convertToEntityAttribute(String dbData) {
return dbData != null ? new IDString(dbData) : null;
}
}

这样,您就不需要对代码进行任何其他修改。AttributeConverter的一个限制是它从正好1个Java字段映射到正好1个DB列。如果你想映射到更多的列(这里不是这样(,你需要嵌入。

您也可以在getter上放置@Column注释:

@Entity
public class Person {
private final IdString idString = new IdString();
@Column(name = "ID_STRiNG")      
public IdString getIdString() {
return idString.getValue();
}
public void setIdString(String input) {
idString.setValue(input);
}

另一个解决方案可能是使用@PostLoad和@PrePersit事件处理程序转换到IdString或从IdString转换:

@Entity
public class Person {
@Column(name = "ID_STRiNG")
private String the_string; // no getters & setters
@Transient
private final IdString idString = new IdString();
@PostLoad
public void postLoad() {
idString.setValue(the_string);
}
@PrePersist
public void prePersist() {
the_string = idString.getValue();
}
// getters & setters for idString 

最新更新