【问题标题】:Hibernate Envers fails with @Converter and AttributeConverter (JPA 2.1)Hibernate Envers 因 @Converter 和 AttributeConverter (JPA 2.1) 而失败
【发布时间】:2014-04-17 00:34:19
【问题描述】:

我正在使用带有 Envers 的 Hibernate 4.3.4 和 MySql 5.6。

如果没有 JPA 2.1 转换器,下面的 Party 实体会在 Configuration.buildSessionFactory() 处失败,因为 Hibernate 不知道如何处理 Name 类:

@Entity
@Audited
public class Party
    {
    protected Name name;
    ...
    }

例外是:

org.hibernate.MappingException: 
  Could not determine type for: 
    ModuloADM.Party.Name, 
    at table: Party, for columns: [org.hibernate.mapping.Column(name)]

为了解决这个问题,我添加了这个转换器:

@Converter (autoApply=true)
public class NametoStringConverter
      implements AttributeConverter<Name, String>
    { ... }

现在异常变为:

org.hibernate.MappingException: 
  Could not determine type for: 
    BasicType adapter for AttributeConverter<Name,String>, 
    at table: History_Party, for columns: [org.hibernate.mapping.Column(name)]

现在在 Party 实体的 Envers 审计表中失败了。请注意,History_Party 是审计表的名称,由 config.setProperty("org.hibernate.envers.audit_table_prefix", "History_") 选择。

完整的堆栈跟踪是:

org.hibernate.MappingException: 
  Could not determine type for: 
    BasicType adapter for AttributeConverter<Name,String>, 
    at table: History_Party, for columns: [org.hibernate.mapping.Column(name)]

  at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:336)
    at org.hibernate.tuple.PropertyFactory.buildEntityBasedAttribute(PropertyFactory.java:246)
    at org.hibernate.tuple.entity.EntityMetamodel.<init>(EntityMetamodel.java:227)
    at org.hibernate.persister.entity.AbstractEntityPersister.<init>(AbstractEntityPersister.java:520)
    at org.hibernate.persister.entity.SingleTableEntityPersister.<init>(SingleTableEntityPersister.java:148)
    at sun.reflect.GeneratedConstructorAccessor43.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
    at org.hibernate.persister.internal.PersisterFactoryImpl.create(PersisterFactoryImpl.java:163)
    at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:135)
    at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:401)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1857)

我该如何解决这个问题? Envers 甚至与 AttributeConverters 兼容吗?

【问题讨论】:

    标签: java hibernate jpa hibernate-envers jpa-2.1


    【解决方案1】:

    尝试在Party 实体中使用@Convert。有时autoApply 标志不起作用

    @Entity
    @Audited
    public class Party
        {
        @Convert(converter = NametoStringConverter.class)
        protected Name name;
        ...
        }
    

    【讨论】:

    • 谢谢,沙赞。我已经对此进行了测试,但它不起作用。即使解决了也无法解决我的问题,因为我需要自动应用。请注意,如果我删除 Envers 审核,自动应用也可以工作。
    • 我们遇到了同样的问题(但没有使用 Envers)并且它可以与 Hibernate 4.3.7.Final 这种方式一起使用 :) .. .应该和dalcorta说的有关,@Column注解可能会导致AttributeConverter上的@Converter(autoApply = true)被忽略。
    • 使用泛型可能是另一个原因:stackoverflow.com/a/28281463/1915920
    • 我的第一条评论:但是我们在另一个子项目/pom 中有一个 未使用的对 Envers 5.1.0.Final 的依赖项 并将其删除(实际上将它从compile 范围设置为provided 就足够了)也修复了它。
    • 我们应用的另一个修复是不要将 映射信息/注释类放在单独的项目中,这些类不会被休眠自动扫描:stackoverflow.com/questions/1780341/…
    【解决方案2】:

    我在异常中看到文本“GeneratedConstructorAccessor43”。可能您需要一个公共 void 构造函数,以便 JPA 可以创建 NametoStringConverter 的实例。

    默认构造函数应该可以工作,但请检查您是否有另一个带有接收参数或不公开的构造函数。

    【讨论】:

    • 除默认构造函数外,不存在其他构造函数。
    • 抱歉,这只是一个假设。感谢您的反馈,如果找到答案,请发布。
    • 我已经放弃了。我想目前 Envers 与 AttributeConverters 不兼容。
    【解决方案3】:

    这似乎是known problem with Hibernate Envers (HHH-9042)

    一个简单的解决方法是手动调用 Convter 和一个额外的瞬态字段,如下所示:

    @Entity
    public class Party {
    
      protected Name name;
    
      @Transient
      protected String nameString;
    
      //...
    
      public void setName(Name name) {
        this.nameString = (new NametoStringConverter()).convertToDatabaseColumn(name);
        this.name = name;
      }
    
      //...
    
      public void setNameString(String nameString) {
        this.name = (new NametoStringConverter()).convertToEntityAttribute(nameString);
        this.nameString = nameString;
      }
    
    }
    

    根据转换函数,代码可以通过将它们设为static并导入它们来进一步简化。

    【讨论】:

    • 嗯,其实我就是你指的HHH-9042票的记者。
    • 啊,我明白了。我在HHH-9042 的评论部分添加了指向此问题的链接,以便在问题关闭后我们可以在此处更新。此外,很高兴知道这是一个“官方”错误,被 Hibernate Envers 团队认为是开放的。
    • 该错误已在几天前报告为已修复,但该修复不会向后移植到 Hibernate 4.3。所以看来我们要么必须等待 5.0,要么回退到用户类型而不是使用 AttributeConvertes。
    【解决方案4】:

    我有同样的问题,我发现它只发生在我没有将带有 columnDefinition = "VARCHAR(255)" 的@Column 注释放入枚举时。所以我认为这是一个比休眠跟踪器更好的解决方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-04
      • 1970-01-01
      • 2011-11-08
      • 2011-07-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多