Я храню коллекцию бесплатных прокси в базе данных. Прокси-объект состоит из:
- 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;
...
}
Каждый раз, когда я сохраняю прокси-объект, я хочу избежать дублирования существующих источников. Например:
Прокси-объект имеет 2 источника:
- с ресурсом = "res1"
- с ресурсом = "res2"
Если исходная таблица уже содержит запись с source = "res1", я хочу заполнить ее свойство id в java-объекте из базы данных, чтобы избежать создания дубликата.
Сейчас я делаю это вручную в своем классе репозитория:
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())));
}
По сути, я проверяю наличие каждого источника в коллекции источников. Если источник с таким же значением ресурса уже существует, я заполняю его идентификатор из базы данных. Непустой идентификатор избегает создания дубликатов.
Это работает, но, возможно, есть более чистое решение этой проблемы?