【问题标题】:JPA Converter unnessecary call of "convertToDatabaseColumn" leads to ClassCastExceptionJPA 转换器对“convertToDatabaseColumn”的不必要调用导致 ClassCastException
【发布时间】:2021-07-09 07:15:48
【问题描述】:

我有一个Converter 将存储在数据库中的String 转换为相应的Enum 元素:

@Converter(autoApply=true)
public class DokumentTypConverter implements AttributeConverter<DokumentTypSchluessel, String> {

   @Override
   public String convertToDatabaseColumn(DokumentTypSchluessel attribute) {
      return attribute.getValue();
   }

   @Override
   public DokumentTypSchluessel convertToEntityAttribute(String dbData) {
      return DokumentTypSchluessel.from(dbData);
   }
}

我有一个实体类,它有一个枚举类型的字段:

@Entity
@Table(name="REF_DOKUMENTTYPEN")
public class DokumentTyp {
   private DokumentTypSchluessel schluessel;
   // snip
}

现在,当我尝试从数据库中检索该实体的实例时

String query = "SELECT d FROM DokumentTyp d WHERE d.schluessel = " + VORBEREITUNG;
entityManager.createQuery(query, DokumentTyp.class).getSingleResult();

我收到以下错误:

javax.persistence.PersistenceException: An exception occurred while calling convertToDatabaseColumn on converter class de.drvbund.pub.model.convert.DokumentTypConverter with value VORBEREITUNG
        at org.eclipse.persistence.mappings.converters.ConverterClass.convertObjectValueToDataValue(ConverterClass.java:139)
        at org.eclipse.persistence.mappings.foundation.AbstractDirectMapping.getFieldValue(AbstractDirectMapping.java:778)
        at org.eclipse.persistence.internal.expressions.QueryKeyExpression.getFieldValue(QueryKeyExpression.java:420)
        at org.eclipse.persistence.internal.expressions.ConstantExpression.printSQL(ConstantExpression.java:152)
        at org.eclipse.persistence.expressions.ExpressionOperator.printDuo(ExpressionOperator.java:2241)
        at org.eclipse.persistence.internal.expressions.CompoundExpression.printSQL(CompoundExpression.java:286)
        at org.eclipse.persistence.internal.expressions.RelationExpression.printSQL(RelationExpression.java:899)
        at org.eclipse.persistence.internal.expressions.ExpressionSQLPrinter.translateExpression(ExpressionSQLPrinter.java:325)
        at org.eclipse.persistence.internal.expressions.ExpressionSQLPrinter.printExpression(ExpressionSQLPrinter.java:129)
        at org.eclipse.persistence.internal.expressions.SQLSelectStatement.printSQL(SQLSelectStatement.java:1755)
        at org.eclipse.persistence.internal.databaseaccess.DatabasePlatform.printSQLSelectStatement(DatabasePlatform.java:3268)
        at org.eclipse.persistence.platform.database.OraclePlatform.printSQLSelectStatement(OraclePlatform.java:967)
        at org.eclipse.persistence.internal.expressions.SQLSelectStatement.buildCall(SQLSelectStatement.java:843)
        at org.eclipse.persistence.internal.expressions.SQLSelectStatement.buildCall(SQLSelectStatement.java:854)
        at org.eclipse.persistence.descriptors.ClassDescriptor.buildCallFromStatement(ClassDescriptor.java:815)
        at org.eclipse.persistence.internal.queries.StatementQueryMechanism.setCallFromStatement(StatementQueryMechanism.java:390)
        at org.eclipse.persistence.internal.queries.StatementQueryMechanism.prepareSelectAllRows(StatementQueryMechanism.java:315)
        at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.prepareSelectAllRows(ExpressionQueryMechanism.java:1723)
        at org.eclipse.persistence.queries.ReadAllQuery.prepareSelectAllRows(ReadAllQuery.java:904)
        at org.eclipse.persistence.queries.ReadAllQuery.prepare(ReadAllQuery.java:835)
        at org.eclipse.persistence.queries.DatabaseQuery.checkPrepare(DatabaseQuery.java:673)
        ... 151 more
Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to de.drvbund.pub.enums.DokumentTypSchluessel

我猜框架从查询中获取Enum元素的toString()-representation,假设它是实体属性值,需要转换为其对应的dbValue并尝试调用convertToDatabaseColumn()方法通过String。我只是不知道如何正确地做到这一点。

如何使用 JPA 检索由 Enum 属性值过滤的实体?

【问题讨论】:

  • 您是否尝试过将值作为参数传递 - 直接使用 Enum 类型而不是 String,因为错误是在形成查询时查找 DokumentTypSchluessel 但获取您的字符串。
  • 是的,我尝试通过使用CriteriaQuery 而不是查询字符串直接使用枚举类型,但它会导致相同的错误。
  • 您是如何准确添加的?您上面的字符串是 JPQL,因此您应该能够只使用 entityManager.createQuery("SELECT d FROM DokumentTyp d WHERE d.schluessel = ?1", DokumentTyp.class).setParameter(1, DokumentTypSchluessel.VORBEREITUNG).getSingleResult(); 而不必诉诸条件查询。如果您尝试使用参数,我预计堆栈会略有不同,并且可能指向略有不同的问题或原因
  • 是的!有了它就可以了!谢谢! :D

标签: java jpa enums eclipselink java-ee-7


【解决方案1】:

在 Chris 的建议下问题解决了:

entityManager.createQuery("SELECT d FROM DokumentTyp d WHERE d.schluessel = ?1", DokumentTyp.class)
             .setParameter(1, DokumentTypSchluessel.VORBEREITUNG)
             .getSingleResult();

【讨论】:

    猜你喜欢
    • 2014-12-10
    • 1970-01-01
    • 1970-01-01
    • 2016-09-03
    • 2020-11-11
    • 2017-04-18
    • 1970-01-01
    • 1970-01-01
    • 2017-10-09
    相关资源
    最近更新 更多