【问题标题】:How to convert joined element collection with JPA 2.1?如何使用 JPA 2.1 转换加入的元素集合?
【发布时间】:2019-10-23 21:50:52
【问题描述】:

我有 3 张桌子 useruser_teamteam ...

user
--------
id (number)
name (varchar)

team
--------
name (varchar)

user_team
--------
user_id (number) FK -> user.id
team_name (varchar) FK -> team.name

我想加载 User 实体,以便将团队转换为正确的类型。

@Entity
public class User implements Serializable {

    @Id
    @GeneratedValue( strategy = IDENTITY )
    private Long id;

    @Column( name = "name" )
    private String name;

    @ElementCollection
    @JoinTable( name = "user_team", 
            joinColumns = @JoinColumn( name = "user_id" ) )
    @Column( name = "team_name" )
    @Convert( converter = TeamToStringConverter.class )
    private Set<Team> teams;
}

public enum Team { NOTEAM, GEEKS, FREAKS, etc ... }

@Converter
public class TeamToStringConverter implements AttributeConverter<Team, String> {

    @Override
    public String convertToDatabaseColumn( Team value ) {
        return value == null ? NOTEAM.name() : value.name();
    }
    @Override
    public TEAM convertToEntityAttribute( String value ) {
        return Team.from( value );
    }
}

我认为问题在于它使用 TeamToStringConverter 转换 user_team.user_id 字段而不是 user_team.team_name 字段(在 @Column 注释中指定),结果是异常:

sql.SqlUtils - Attempted to convert SQLException to SQLException. Leaving it alone. [SQLState: null; errorCode: 0]
com.microsoft.sqlserver.jdbc.SQLServerException: An error occurred while converting the nvarchar value to JDBC data type INTEGER.
at com.microsoft.sqlserver.jdbc.DDC.convertStreamToObject(DDC.java:475)
at com.microsoft.sqlserver.jdbc.ServerDTVImpl.getValue(dtv.java:2536)
...
Caused by: java.lang.NumberFormatException: For input string: "NOTEAM"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:580)
...

【问题讨论】:

    标签: java entity-framework jpa


    【解决方案1】:

    将映射改为

    @ElementCollection
    @CollectionTable( name = "user_team", 
            joinColumns = @JoinColumn( name = "user_id" ) )
    @Column( name = "team_name" )
    @Enumerated(EnumType.STRING)
    @Convert( converter = TeamToStringConverter.class )
    private Set<Team> teams;
    

    应该使用@CollectionTable 而不是@JoinTable,并且@Enumerated(EnumType.STRING) 告诉JPA枚举值在数据库中存储为String,而不是默认的Integer(枚举常量的索引)。

    请注意,表team 在此设置中对 JPA 没有任何意义,因为它没有映射到任何东西。

    【讨论】:

      【解决方案2】:

      在低于 4.3.9 的 Hibernate 版本中,@Convert 注释不适用于集合字段。

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

      对于低于 4.3.9 的 Hibernate,使用 autoApply 属性:

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

      对于更高版本的 Hibernate 4.3.9 使用:

      @ElementCollection
      @CollectionTable( name = "user_team", joinColumns = @JoinColumn( name = "user_id" ) )
      @Column( name = "team_name" )
      @Convert( converter = TeamToStringConverter.class )
      private Set<Team> teams;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-20
        • 1970-01-01
        • 1970-01-01
        • 2016-02-19
        • 2017-11-28
        相关资源
        最近更新 更多