【问题标题】:Hibernate - Cannot insert new record when using composite primary key (@idClass), given keeping its auto-generated attributeHibernate - 使用复合主键(@idClass)时无法插入新记录,因为它保留了自动生成的属性
【发布时间】:2019-05-03 18:18:37
【问题描述】:

我会尽量简单。我有一个表,其复合主键由两个 Long 属性组成,由 @IdClass 注释类包装。

@IdClass 属性:

public class MyPK implements Serializable {
    private Long id;
    private Long version;
} // + hashCode, constructors, etc.

我没有做的事情:

插入一条新记录,同时保持“id”的值并递增“version”。

示例场景:

现有记录 - {id:1, version:1}

所需的新记录(未更新,正在谈论新记录) - {id:1, version:2}

我做了什么:

起初我尝试增加版本,同时保留我正在使用的序列生成器。以下是 id 的注释方式:

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "idSequence")
@SequenceGenerator(name = "idSequence", sequenceName = "SQ_ID", allocationSize = 1)
@Column(name = "ID", nullable = false, updatable = false)
private Long id;

以上导致提供的 id 被序列的 nextVal 覆盖,所以对我来说没有任何交易。

所以我的第二种方法是使用继承和内部 Hibernate 类,这是我一直尽量避免的:

public class MySequenceStyleIdGenerator extends SequenceStyleGenerator {

    @Override
    public Serializable generate(SessionImplementor session, Object object){
        Serializable id = session.getEntityPersister(null, object)
                .getClassMetadata().getIdentifier(object, session);

        return id != null && ((MyPK)id).getId() != null
                ? id : super.generate(session, object);
    }

}

并根据需要对实体类进行更改:

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "providedIdOrSequence")
@GenericGenerator(
        name="providedIdOrSequence",
        strategy="{package}.MySequenceStyleIdGenerator",
        parameters = @org.hibernate.annotations.Parameter(
                name = "sequence_name",
                value = "SQ_ID"
        )
)
@Column(name = "ID", nullable = false, updatable = false)
private Long id;

另一方面,只有当它为空时,它才会将 nextVal 返回到 id 中,这正是我想要的。然后问题转移到库中更深更深的地方,好像它试图将 id (Long) 分配给 PK 类型本身而不是其 Long 属性:

java.lang.IllegalArgumentException:无法设置 java.lang.Long 字段 {package}.CotacaoPK.idCotacao 到 {package}.CotacaoPK

如果两个 PK 属性(id 和版本)都保持不变,那么我不会出错。

有什么想法吗?我已经投入了合理的时间......谢谢。

【问题讨论】:

    标签: hibernate jpa composite-primary-key spring-repositories sequence-generators


    【解决方案1】:

    问题解决了!

    问题出在我的 SequenceStyleGenerator 实现中。 super.generate(...) 返回一个 Long,但我将 id 作为包装 MyPK 对象返回。所以解决方案是:

    public class MySequenceStyleIdGenerator extends SequenceStyleGenerator {
    
    @Override
    public Serializable generate(SessionImplementor session, Object object){
            Serializable id = session.getEntityPersister(null, object)
                    .getClassMetadata().getIdentifier(object, session);
    
            return id != null && ((MyPK)id).getId() != null
                    ? ((MyPK)id).getId() : super.generate(session, object);
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 2016-12-23
      • 2012-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-11
      • 2023-03-10
      • 2019-06-30
      • 1970-01-01
      相关资源
      最近更新 更多