假设我javax.persistence.AttributeConverter调用了实现,FooConverter并且我想将此转换器应用于特定的实体字段。
如果我使用注释方法,它看起来像:
@Column
@Convert(converter = FooConverter.class)
private String barField;
Run Code Online (Sandbox Code Playgroud)
在 orm XML 映射上,它看起来像:
<entity class="com.example.FooBarEntity">
<convert converter="com.example.FooConverter" attribute-name="barField"/>
</entity>
Run Code Online (Sandbox Code Playgroud)
但是,我想在javax.persistence.EntityManagerFactory配置期间以编程方式添加此转换器。
import org.hibernate.cfg.Configuration;
import org.springframework.orm.hibernate5.LocalSessionFactoryBuilder;
private EntityManagerFactory buildEntityManagerFactory() {
Configuration config = new LocalSessionFactoryBuilder(dataSource);
config.addAnnotatedClass(com.example.FooBarEntity.class);
// I looking for something like config.addConverter(FooConverter, FooBarEntity, barField);
return config.buildSessionFactory();
}
Run Code Online (Sandbox Code Playgroud)
有config.addAttributeConverter方法,但它似乎只创建转换器实例,而不是将其绑定到特定的实体属性。但是,我只想将转换器应用于特定String领域,所以autoApply不是一个选项。
JPA 规范仅提供 2 个应用转换器的选项:全局@Converter(autoApply = true)和字段级@Convert(converter = FooConverter.class)(或其 XML 等效项)。
JPA 转换器仅了解实体属性类型和数据库列类型。无法访问实体实例甚至实体类型来构建条件(按实体字段)转换逻辑。
AttributeConverter您可以像这样以编程方式添加转换器:
LocalSessionFactoryBuilder builder = new LocalSessionFactoryBuilder(dataSource);
builder.addAnnotatedClasses(FooBarEntity.class);
builder.addAttributeConverter(FooConverter.class, /*autoApply:*/true);
EntityManagerFactory entityManagerFactory = builder.buildSessionFactory();
Run Code Online (Sandbox Code Playgroud)
我不确定是否有比@Convert(converter = FooConverter.class).
仅将转换器应用于特定实体字段的解决方法:
为需要转换的字符串创建包装器:
public class Bar {
private final String value;
public Bar(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
@Entity
public class FooBarEntity {
private Bar barField;
public void setBarField(String value) {
this.barField = new Bar(value);
}
//...
}
Run Code Online (Sandbox Code Playgroud)
声明一个自动应用的转换器:
@Converter(autoApply = true)
public class FooConverter implements AttributeConverter<Bar, String> {
@Override
public String convertToDatabaseColumn(Bar bar) {
return Optional.ofNullable(bar).map(Bar::getValue/*anything*/).orElse(null);
}
@Override
public Status convertToEntityAttribute(String value) {
return Optional.ofNullable(value).map(Bar::new).orElse(null);
}
}
Run Code Online (Sandbox Code Playgroud)
如果从 转换String为String(源类型和目标类型相同),则可以使用实体侦听器。实体侦听器可以访问实体本身,因此可以具有复杂的条件逻辑。
@Entity
public class FooBarEntity {
private String barField;
}
Run Code Online (Sandbox Code Playgroud)
创建实体监听器:
public class FooEntityListener {
@PrePersist
@PreUpdate
public void convertToDatabaseColumn(Object entity) {
if (entity instanceof FooBar) {
entity.setBarField(/*conversion to DB column*/entity.getBarField());
}
}
@PostLoad
public void convertToEntityAttribute(Object entity) {
if (entity instanceof FooBar) {
entity.setBarField(/*conversion to entity attribute*/entity.getBarField());
}
}
}
Run Code Online (Sandbox Code Playgroud)
在META-INF/orm.xml中注册默认实体侦听器:
<entity-mappings>
<persistence-unit-metadata>
<persistence-unit-defaults>
<entity-listeners>
<entity-listener class="com.example.FooEntityListener"/>
</entity-listeners>
</persistence-unit-defaults>
</persistence-unit-metadata>
</entity-mappings>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1373 次 |
| 最近记录: |