【问题标题】:Can JPA @Converter be used in a Map Mapping using @MapKey?JPA @Converter 可以在使用@MapKey 的地图映射中使用吗?
【发布时间】:2014-01-30 23:27:07
【问题描述】:

我在使用 Hibernate Map 集合映射时遇到问题,其中键是一个枚举,该枚举具有应附加到它的转换器。

使用 JPA 2.1 转换器的用户角色枚举

public enum UserRoleDefinition {USER,ADMIN}

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

  public String convertToDatabaseColumn(UserRoleDefinition attribute)
  {
    return attribute.getName();
  }


  public UserRoleDefinition convertToEntityAttribute(String dbData)
  {
    return UserRoleDefinition.parse(dbData);
  }
}

为清楚起见,删除了 UserRole 实体的非必要属性

@Entity
public class UserRole 
{
     @ManyToOne
    @JoinColumn(name = "user_account_fk")
    private UserAccount userAccount; 

    @Column(name = "role_definition_fk")
    @Convert(converter = UserRoleDefinitionConverter.class)
    private UserRoleDefinition roleDefinition;
}

为清楚起见,删除了 UserAccount 实体的非必要属性

@Entity
public class UserAccount 
{ 
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "userAccount", cascade = CascadeType.ALL)
    @MapKey(name = "roleDefinition")
    private Map<UserRoleDefinition, UserRole> userRoles = new HashMap<>();
} 

当我运行应用程序时,出现以下异常。

Caused by: javax.persistence.PersistenceException: [PersistenceUnit: test] Unable to build Hibernate SessionFactory
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:1225)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.access$600(EntityManagerFactoryBuilderImpl.java:119)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:853)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:843)
    at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:399)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:842)
    at org.hibernate.jpa.HibernatePersistenceProvider.createContainerEntityManagerFactory(HibernatePersistenceProvider.java:150)
    at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:67)
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:318)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:318)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1612)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1549)
    ... 44 more
Caused by: org.hibernate.MappingException: No type name
    at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:319)
    at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:310)
    at org.hibernate.mapping.IndexedCollection.validate(IndexedCollection.java:90)
    at org.hibernate.cfg.Configuration.validate(Configuration.java:1362)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1849)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:850)
    ... 53 more

我已经尝试了各种映射的变体,我已经追踪到 hiberante 源代码以试图了解为什么事情不工作。在此过程中,我确定转换器已正确注册到休眠状态,并且我的配置是正确的。

我想要在 JPA 2.1 中进行的映射是否合法?如果不是为什么不呢?如果是的话,任何想法是什么导致了我这个问题?

【问题讨论】:

  • 看起来验证正在试图找出密钥类型,但不能。如果您正在追踪源,请检查 SimpleValue 是否是它应该使用的。您可以尝试使用其他提供商来查看它是否受支持,因为我不明白为什么不支持。
  • @Converter(autoApply = true) 足以转换项目中的每个UserRoleDefinition 类型,因此您可以删除roleDefinition 字段中的@Convert(converter = UserRoleDefinitionConverter.class)
  • attribute.getName()UserRoleDefinition.parse(dbData) 到底是做什么的?

标签: java hibernate jpa eclipselink openjpa


【解决方案1】:

这是一个 Hibernate 错误,已在 5.0.4 版本中解决。

https://hibernate.atlassian.net/browse/HHH-9475

【讨论】:

    【解决方案2】:

    看来您使用UserRoleDefinitionConverterUserRoleDefinition 持久化为字符串值并将其作为枚举值取回,所以我认为最好使用@MapKeyEnumerated@Enumerated,这样您就可以删除@ 987654325@ class 并更改您的代码如下:

    用户角色

    @Entity
    public class UserRole 
    {
        @ManyToOne
        @JoinColumn(name = "user_account_fk")
        private UserAccount userAccount; 
    
        @Enumerated(EnumType.STRING)
        @Column(name = "role_definition_fk")
        private UserRoleDefinition roleDefinition;
    
        //Other stuff...
    }
    

    用户帐户

    @Entity
    public class UserAccount 
    { 
        @OneToMany(fetch = FetchType.LAZY, mappedBy = "userAccount", cascade = CascadeType.ALL)
        @MapKey(name = "roleDefinition")
        @MapKeyEnumerated(EnumType.STRING)
        private Map<UserRoleDefinition, UserRole> userRoles = new HashMap<>();
    
        //Other stuff...
    } 
    

    注意:我知道这是一个老问题,但我希望它可以帮助其他人。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-22
      • 1970-01-01
      • 2013-03-11
      相关资源
      最近更新 更多