SpringBoot JPA 2.1 Converter 忽略 convertToDatabaseColumn
Posted
技术标签:
【中文标题】SpringBoot JPA 2.1 Converter 忽略 convertToDatabaseColumn【英文标题】:SpringBoot JPA 2.1 Converter ignores convertToDatabaseColumn 【发布时间】:2020-02-25 16:58:10 【问题描述】:我有以下转换器
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
@Converter(autoApply = true)
public class ImportedReasonConverter implements AttributeConverter<ImportedReason, String>
@Override
public String convertToDatabaseColumn(final ImportedReason pImportedReason)
return pImportedReason.getValue();
@Override
public ImportedReason convertToEntityAttribute(final String pImportedReason)
return ImportedReason.of(pImportedReason);
被诸如
之类的实体使用@Entity
@Table(
name = "IMPORT_RECORD"
)
public class ImportRecordEntity implements Serializable
private static final long serialVersionUID = 2483327758356663412L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID")
private UUID id;
@Column(name = "importedReason")
private ImportedReason importedReason;
public ImportedReason getImportedReason()
return importedReason;
public void setImportedReason(final ImportedReason importedReason)
this.importedReason = importedReason;
...
启动应用程序后,表由 Hibernate 创建,使用正确的列类型(此处为:VARCHAR)。删除 autoApply=true 设置会导致启动失败 - 因此转换器本身会被识别。
但是:在保存实体时将值设置为importedReason,我得到一个
Caused by: java.io.NotSerializableException: ImportedReason
at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1185)
at java.base/java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1553)
at java.base/java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1510)
at java.base/java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1433)
at java.base/java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1179)
at java.base/java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:349)
at org.hibernate.internal.util.SerializationHelper.serialize(SerializationHelper.java:115)
... 43 more
尝试调试我的转换器,方法 ImportedReasonConverter.convertToDatabaseColumn(ImportedReason) 没有被调用。因此 Hibernate 不会尝试写入 String 类型的值,而是输入 ImportedReason。
任何想法,为什么转换器不能正确使用?我已经使用 Java 8 + 11 和 Spring 2.1.5.RELEASE + 2.1.9.RELEASE (早期版本用于另一个项目)进行了尝试。 我也尝试过使用其他一些转换器(例如内部类型 -> LocalDateTime),但我在这里也遇到了同样的问题。
非常感谢。 斯蒂芬
【问题讨论】:
'@Column(name = "importedReason") @Converter(.......) private ImportedReason importReason;' @Zorglube 不,这不会改变它 真的!?奇怪,你的注释是这样的吗?@Convert(converter = ImportedReasonConverter.class)
,调试是否显示您通过 convertToDatabaseColumn
、convertToEntityAttribute
方法?
我都尝试了,在转换器本身上设置 autoApply = true 并在实体的属性中添加 @Converter。转换器似乎被使用的两种方式(表格设置正确),但是当涉及到将它用于引用的实体时,它变得不可见。请参阅我的答案 - 我试图在那里更详细地描述它。
【参考方案1】:
更新: 进一步的调查表明,正在保存的实体已经过全面分析,并且其转换器得到了正确使用。 但是:如果该实体使用其他一些实体作为引用,而后者又使用要使用这些转换器转换的类型:那是它看到值但不使用转换器(出于某种原因)的时候。
所以我上面的 ImportRecordEntity 用于以下 PortfolioEntity,我实际上正在尝试保存它。保存 ImportRecordEntity 毫不费力。然后我将这个 ImportRecordEntity 实例(从保存方法返回)设置为 PortfolioEntity 实例并保存它。但是随后 Hibernate 崩溃了,因为它似乎分析了 PortfolioEntity 而不是 ImportRecordEntity ,它持有 ImportedReason - 所以它不知道 ImportedReasonConverter (参见 org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(Object, EntityKey, EntityPersister, boolean, Object, EventSource, boolean) - AbstractSaveEventListener.java:122 变量类型)。
@Entity
@Table(
name = "PORTFOLIO"
)
public class PortfolioEntity implements Serializable
private static final long serialVersionUID = 3632725596750538287L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID")
private UUID id;
@Column(name = "IMPORT_RECORD")
private ImportRecordEntity importRecord;
...
【讨论】:
【参考方案2】:哦,天哪……这太垃圾了……
我忘了这是@OneToOne 映射
我的实体需要如下设置:
@Entity
@Table(
name = "PROVIDER_PORTFOLIO"
)
public class PortfolioEntity implements Serializable
private static final long serialVersionUID = 3632725596750538287L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID")
private UUID id;
@OneToOne
@JoinColumn(
name = "IMPORT_RECORD_ID"
)
private ImportRecordEntity importRecord;
[...]
@Entity
@Table(
name = "IMPORT_RECORD"
)
public class ImportRecordEntity implements Serializable
private static final long serialVersionUID = 2483327758356663412L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID")
private UUID id;
@Column(name = "importedReason")
private ImportedReason importedReason;
[...]
好吧...抱歉给您带来了困惑,应该刚刚停止工作;)
斯蒂芬
【讨论】:
以上是关于SpringBoot JPA 2.1 Converter 忽略 convertToDatabaseColumn的主要内容,如果未能解决你的问题,请参考以下文章
带有 Spring Boot 和 websphere 8.5.0.1 的 JPA 2.1