【发布时间】:2019-06-13 17:31:45
【问题描述】:
我在数据库中存储了一组免费代理。代理实体包括:
- IP 地址
- 端口
- 来源列表
Source 基本上是我在其中找到此代理信息的网站。这是我的架构:
代理表:
+--------------+-------------+------+-----+---------+-------+
| 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;
...
}
每当我保存代理对象时,我都想避免重复现有的源。例如:
代理对象有 2 个来源:
- 资源 = "res1"
- 资源 = "res2"
如果源表已经包含 source = "res1" 的条目,我想从数据库中将它的 id 属性填充到 java 对象中以避免创建重复。
现在我在我的 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 避免创建重复。
它有效,但可能有更清洁的解决方案来解决这个问题?
【问题讨论】:
标签: java mysql spring hibernate orm