休眠-使用复合主键(@idClass)时无法插入新记录,原因是保留其自动生成的属性

时间:2019-05-03 18:18:37

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

我会尽量简化。我有一个表,该表具有由两个Long属性组成的复合主键,并由@IdClass带注释的类包装。

@IdClass属性:

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

我没有做的事情

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

示例场景:

现有记录-{id:1,版本: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;

另一方面,这仅在null为null时才将nextVal返回到id,这正是我想要的。然后问题转移到库中越来越暗的地方,就好像它试图将id(Long)分配给PK类型本身而不是其Long属性一样:

enter image description here

  

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

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

有什么想法吗?我已经花了几个小时了...谢谢。

1 个答案:

答案 0 :(得分:0)

问题解决了!

问题出在我的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);
    }

}