java - JPA @Converter 可以在使用 @MapKey 的 map 映射中使用吗?

标签 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 中合法吗?如果不,为什么不呢?如果是的话,知道是什么导致了我这个问题吗?

最佳答案

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

用户角色

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

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

关于java - JPA @Converter 可以在使用 @MapKey 的 map 映射中使用吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21070592/

相关文章:

hibernate 和复合键

database - @JoinColumn 和 mappedBy 用于拥有方和反方

java - 如何使用实体管理器使用查询将值插入数据库,使用 java 类进行持久化?

java - 为什么 JVM 的实际内存占用比我的 Xmx 大这么多?

java - Spring 集成 SFTP - 传输后处理

Gradle 中的 Java 8 构建错误

java - Spring Roo + hibernate : uppercase database name in the query

java - ftp 文件检索未完成的文件

java - org.hibernate.boot.registry.classloading.spi.ClassLoadingException:无法加载类[emp.hbm.xml]

java - jpa引用外部表而不是JoinColumn中的外部列