可以使用@MapKey在地图映射中使用JPA @Converter吗?

时间:2014-01-12 02:29:25

标签: java hibernate jpa eclipselink openjpa

我遇到了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源代码,试图理解为什么事情不起作用。在这个过程中我确定转换器已正确注册hibernate,我的配置是正确的。

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

2 个答案:

答案 0 :(得分:1)

您似乎正在使用UserRoleDefinitionConverterUserRoleDefinition作为字符串值保留并将其作为枚举值返回,因此我认为使用{{3}会更好}和@MapKeyEnumerated,因此您可以删除UserRoleDefinitionConverter类并更改代码,如下所示:

<强>的UserRole

@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...
}

<强> UserAccount

@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...
} 

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

答案 1 :(得分:0)

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

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