gpt4 book ai didi

java - Hibernate:使用 EntityManager 插入更新

转载 作者:行者123 更新时间:2023-11-29 21:25:19 25 4
gpt4 key购买 nike

我有一个对一个字段具有唯一约束的表,我想设置 Hibernate EntityManager,以便仅当没有此类记录时它才会插入新记录,并且会以其他方式更新。

我的表 POJO 看起来是这样的:

@Entity
@Table(name = "links", uniqueConstraints = {
@UniqueConstraint(columnNames = "link", name = "uk_link")
})
public class Link {

private long linkId;
private String link;
private String data;
private String metadata;

private List<Result> results;

@Id
@Column(name="link_id")
@GeneratedValue(strategy=GenerationType.IDENTITY)
public long getLinkId() {
return linkId;
}

public void setLinkId(long linkId) {
this.linkId = linkId;
}

public String getLink() {
return link;
}

public void setLink(String link) {
this.link = link;
}

public String getData() {
return data;
}

public void setData(String data) {
this.data = data;
}

public String getMetadata() {
return metadata;
}

public void setMetadata(String metadata) {
this.metadata = metadata;
}

@OneToMany(cascade=CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "link")
public List<Result> getResults() {
return results;
}

public void setResults(List<Result> results) {
this.results = results;
}

@Override
public String toString() {
return "Link [linkId=" + linkId + ", link=" + link + ", data=" + data + ", metadata=" + metadata + "]";
}

public boolean isDataEquals(String data) {
if (this.data == null) {
if (data != null)
return false;
} else if (!this.data.equals(data))
return false;
return true;
}

public boolean isMetadataEquals(String metadata) {
if (this.metadata == null) {
if (metadata != null)
return false;
} else if (!this.metadata.equals(metadata))
return false;
return true;
}
}

我尝试通过此代码解决必要的更改:

public Link selectByLink(String link) {
return entityManager
.createQuery("select l from Link l WHERE l.link = :link", Link.class)
.setParameter("link", link)
.getSingleResult();
}

public void insert(Link link) {
this.entityManager.persist(link);
}

public Link update(Link link) {
return this.entityManager.merge(link);
}

public void save(Link link) {
if (link.getLinkId() == 0) {
Link _existing = selectByLink(link.getLink());
if (null != _existing) {
link.setLinkId(_existing.getLinkId());
if (!_existing.isDataEquals(link.getData()) ||
!_existing.isMetadataEquals(link.getMetadata())) {
update(link);
}
} else
insert(link);
}
}

在 Spring 日志中,我看到一个额外的选择:

Hibernate: select link0_.link_id as link_id1_0_, link0_.data as data2_0_, link0_.link as link3_0_, link0_.metadata as metadata4_0_ from links link0_ where link0_.link=?
Hibernate: select link0_.link_id as link_id1_0_1_, link0_.data as data2_0_1_, link0_.link as link3_0_1_, link0_.metadata as metadata4_0_1_, results1_.link_id as link_id1_1_3_, results1_.text_id as text_id2_1_3_, results1_.link_id as link_id1_1_0_, results1_.text_id as text_id2_1_0_, results1_.found as found3_1_0_, results1_.level as level4_1_0_ from links link0_ left outer join results results1_ on link0_.link_id=results1_.link_id where link0_.link_id=?
Hibernate: update links set data=?, link=?, metadata=? where link_id=?

我猜,发生这种情况是因为我使用合并功能,但如果我在合并之前不搜索对象 ID,则合并将尝试插入对象而不是更新它。有没有办法只更新对象而不先测试它?

还有一个不相关的问题,SQL 看起来非常困惑。所有这些link0_.link_id为link_id1_0_,它们可以被抑制吗?

最佳答案

额外的连接是由于您懒惰的一对多关系而产生的。除了链接本身的 select 之外,还执行额外的 select 语句来加载集合(这就是著名的 N+1 问题的根源)。

并且,对于更新之前执行的选择,这似乎是 hibernate 持续的方式 by default ,当实体分离时。如果您想避免它,您应该使用它的配置(有一个 select-before-update 属性)或自己编写更新查询。您也可以尝试避免 Spring 分离 Hibernate 实体。

关于java - Hibernate:使用 EntityManager 插入更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35536460/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com