gpt4 book ai didi

java - 如何更新@OneToMany 集合中的现有条目?

转载 作者:行者123 更新时间:2023-11-30 21:35:10 24 4
gpt4 key购买 nike

我在数据库中存储了一组免费代理。代理实体包括:

  • IP地址
  • 港口
  • 来源列表

来源基本上是我找到此代理信息的网站。这是我的架构:

代理表:

+--------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+-------+
| id | varchar(45) | NO | PRI | NULL | |
| ip_address | varchar(40) | NO | | NULL | |
| port | smallint(6) | NO | | NULL | |
+--------------+-------------+------+-----+---------+-------+

来源:

+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| resource | varchar(200) | NO | | NULL | |
+----------+--------------+------+-----+---------+----------------+

连接前两个表的 proxy_sources:

+-----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| proxy_id | varchar(45) | NO | MUL | NULL | |
| source_id | int(11) | NO | MUL | NULL | |
+-----------+-------------+------+-----+---------+-------+

我的 Java ORM 类:

@Entity
@Table(name = "proxy")
public class Proxy {

@Id
@Column(name = "id")
private String id;

@Column(name = "ip_address")
private String ipAddress;

@Column(name = "port")
private int port;

@OneToMany(cascade = CascadeType.MERGE, fetch = FetchType.EAGER)
@JoinTable(
name = "proxy_sources",
joinColumns = @JoinColumn(name = "proxy_id"),
inverseJoinColumns = @JoinColumn(name = "source_id")
)
private List<Source> sources = new ArrayList<>();

...
}


@Entity
@Table(name = "source")
public class Source {

@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;

@Column(name = "resource")
private String resource;

...
}

每当我保存代理对象时,我都希望避免复制现有源。例如:

代理对象有两个来源:

  1. 资源=“res1”
  2. 资源=“res2”

如果源表已经包含带有 source = "res1"的条目,我想在数据库中的 java 对象中填充它的 id 属性,以避免创建重复项。

现在我在我的 Repository 类中手动完成:

public String save(Proxy proxy) {
populate(proxy.getSources());
return (String) sessionFactory.getCurrentSession().save(proxy);
}

这是填充方法:

private void populate(List<Source> sources) {
if (sources.isEmpty()) {
return;
}

List<String> resources = sources.stream().map(Source::getResource).collect(toList());

List<Source> existing = sessionFactory.getCurrentSession()
.createQuery("FROM Source source WHERE source.resource IN (:resources)", Source.class)
.setParameterList("resources", resources)
.list();

sources.forEach(source -> existing.stream()
.filter(s -> s.getResource().equals(source.getResource()))
.findAny()
.ifPresent(s -> source.setId(s.getId())));
}

基本上我所做的是检查来源集合中的每个来源是否存在。如果具有相同资源值的源已经存在,我会从数据库中填充它的 ID。非空 ID 避免创建重复项。

它有效,但可能有更简洁的解决方案来解决这个问题?

最佳答案

为避免重复,您可以进行的第一个修改是在 source 表中的 resource 列上创建一个唯一键。这样即使您在代码中犯了错误,如果您尝试保存重复的寄存器,数据库也会抛出错误。

话虽如此,要仅保存数据库中不存在的对象并没有简单的方法。您要么将 resource 列作为您的主键并丢弃 id 列(我认为这不是一个好的选择),要么您必须进行选择在数据库上。

This question has more details on the second option

如果您愿意更改应用程序流程,解决此问题的一种方法是将代理保存分为两个步骤。首先注册所有源,保存所有源后开始注册代理。这样您就知道,当您保存代理时,它已经预先保存了所有源,使您此时的工作仅链接到 Proxy 实体上的现有源。

关于java - 如何更新@OneToMany 集合中的现有条目?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54271117/

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