我会尽量简单地说。我有一个由两个 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 为 null 时将其返回到 id 中,这正是我想要的。然后问题转移到库中更暗更深的地方,好像它试图将 id (Long) 分配给 PK 类型本身而不是其 Long 属性:
java.lang.IllegalArgumentException:无法将 java.lang.Long 字段 {package}.CotacaoPK.idCotacao 设置为 {package}.CotacaoPK
如果两个 PK 属性(id 和版本)都保持不变,那么我不会出错。
有任何想法吗?我已经投入了合理的时间......谢谢。