我没想到会这样。
我有一个简单的JPA实体:
@Entity
@Audited(targetAuditMode = NOT_AUDITED)
@NamedQueries({
@NamedQuery(
name = "getShredInfoByDocUUID",
query = "SELECT I FROM DocShreddingExtension I WHERE " +
"I.document2.UUID = :uuid"
)
})
@EntityListeners({
ShreddingListener.class,
})
@JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id",
scope = DocShreddingExtension.class
)
public class DocShreddingExtension implements Serializable {
@OneToOne
@JoinColumn(name = "code")
private ShreddingType shreddingType;
@Id
@OneToOne
@JoinColumn(name = "uuid")
private Document2 document2;
public DocShreddingExtension() {
}
public DocShreddingExtension(Document2 doc, ShreddingType type) {
this();
this.document2 = doc;
this.shreddingType = type;
}
public ShreddingType getShreddingType() {
return shreddingType;
}
public void setShreddingType(ShreddingType shreddingType) {
this.shreddingType = shreddingType;
}
public Document2 getDocument2() {
return document2;
}
public void setDocument2(Document2 document2) {
this.document2 = document2;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DocShreddingExtension that = (DocShreddingExtension) o;
return Objects.equals(shreddingType, that.shreddingType) &&
Objects.equals(document2, that.document2);
}
@Override
public int hashCode() {
return Objects.hash(shreddingType, document2);
}
}和DAO upsert方法:
public void upsert(DocShreddingExtension shreddingInfo) {
DocShreddingExtension saved = entityManager.find(DocShreddingExtension.class, shreddingInfo);
if (saved == null)
entityManager.persist(shreddingInfo);
else
entityManager.merge(shreddingInfo);
}Document2模型类:
@Table(name = "document")
@Entity
@Audited
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonIdentityInfo(
generator = ObjectIdGenerators.IntSequenceGenerator.class,
scope = Document2.class
)
public class Document2 implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name = "doc_uuid")
private long id;
@Column(name = "uuid")
private String UUID;
@Column(name = "extId")
private String extId;
@ManyToOne(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
@JoinColumn(name = "documentType")
private DocType docType;
@OneToMany(mappedBy = "document2", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<DocVersion> docVersions;
@Column(name = "entityState")
@Enumerated(EnumType.STRING)
private EDocState eDocState;
@ManyToOne
@JoinColumn(name = "party_id")
private PartyKind partyContainer;
@OneToMany(mappedBy = "rootDoc", cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
private List<RelatedDoc> relatedDocs;
@ElementCollection
@CollectionTable(name = "product_instance", joinColumns = @JoinColumn(name = "doc_uuid"))
@Column(name = "productInstance")
private List<String> productInstanceIds;
public int change;
public Document2() {
this.docVersions = new HashSet<>();
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUUID() {
return UUID;
}
public void setUUID(String UUID) {
this.UUID = UUID;
}
public String getExtId() {
return extId;
}
public void setExtId(String extId) {
this.extId = extId;
}
public DocType getDocType() {
return docType;
}
public void setDocType(DocType docType) {
this.docType = docType;
}
public Set<DocVersion> getDocVersions() {
return docVersions;
}
public void setDocVersions(Set<DocVersion> docVersions) {
this.docVersions = docVersions;
}
public EDocState geteDocState() {
return eDocState;
}
public void seteDocState(EDocState eDocState) {
this.eDocState = eDocState;
}
public void addDocVersion(DocVersion version) {
this.docVersions.add(version);
}
public PartyKind getPartyContainer() {
return partyContainer;
}
public void setPartyContainer(PartyKind partyContainer) {
this.partyContainer = partyContainer;
}
public List<RelatedDoc> getRelatedDocs() {
return relatedDocs;
}
public void setRelatedDocs(List<RelatedDoc> relatedDocs) {
this.relatedDocs = relatedDocs;
}
public List<String> getProductInstanceIds() {
return productInstanceIds;
}
public void setProductInstanceIds(List<String> productInstanceIds) {
this.productInstanceIds = productInstanceIds;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Document2 document2 = (Document2) o;
return Objects.equals(UUID, document2.UUID);
}
@Override
public int hashCode() {
return Objects.hash(UUID);
}
}我这样做的目的是检查实体是否已经存在于数据库中,并根据这一点保存或合并它。
发生的情况是,找到了实例,因此设置了“saved”,但同时“shreddingInfo”更改了“saved”实例的更改,因此当我调用.merge()时,没有需要合并的内容。
问题是为什么实体管理器要更改.find()方法中的参数?我想这不是故意的。
发布于 2018-03-06 20:44:14
find方法期望主键作为第二个参数。但是你通过了实体!
这导致了这种意外的行为。
您的映射不正确,当您有共享主键时,必须使用@PrimaryKeyJoinColumn:
public class DocShreddingExtension implements Serializable {
@Id
private String uuid;
@OneToOne
@JoinColumn(name = "code")
private ShreddingType shreddingType;
@OneToOne
@PrimaryKeyJoinColumn
private Document2 document2;
}现在,您可以使用uuid调用find。
在这里找到更多信息:http://websystique.com/hibernate/hibernate-one-to-one-unidirectional-with-shared-primary-key-annotation-example/
https://stackoverflow.com/questions/49130082
复制相似问题