У меня есть две сущности, связанные N с N через таблицу отображения, которая сама является сущностью следующим образом
Rule 1<-->N Mapping N<-->1 Preference
Обе они реализуют связь с HashSet <>
Rule.java
/**
* List of {@link RulePreferenceMapping} belonging to this {@link Rule}
*/
@OneToMany(
mappedBy = "rule",
cascade = CascadeType.ALL,
fetch = FetchType.EAGER
)
private Set<RulePreferenceMapping> preferenceMappingList = new HashSet<>();
@Override
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (o == null || getClass() != o.getClass())
{
return false;
}
return new EqualsBuilder()
.appendSuper(super.equals(o))
.isEquals();
}
@Override
public int hashCode()
{
return new HashCodeBuilder(17, 37)
.appendSuper(super.hashCode())
.toHashCode();
}
RulePreference.java
/**
* List of {@link RulePreferenceMapping} pointing to this element
*/
@OneToMany(
mappedBy = "rulePreference",
cascade = CascadeType.ALL,
fetch = FetchType.EAGER
)
private Set<RulePreferenceMapping> ruleMappingList = new HashSet<>();
@Override
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (o == null || getClass() != o.getClass())
{
return false;
}
RulePreference that = (RulePreference) o;
return new EqualsBuilder()
.append(name, that.name)
.isEquals();
}
@Override
public int hashCode()
{
return new HashCodeBuilder(17, 37)
.append(name)
.toHashCode();
}
RulePreferenceMapping.java
/**
* {@link Rule} this element belongs to
*/
@ManyToOne(optional = false, fetch = FetchType.EAGER)
@JoinColumn(name = "rule_id")
private Rule rule;
/**
* {@link RulePreference} this mapping points to
*/
@ManyToOne(optional = false, fetch = FetchType.EAGER)
@JoinColumn(name = "rule_preference_id")
private RulePreference rulePreference;
@Override
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (o == null || getClass() != o.getClass())
{
return false;
}
RulePreferenceMapping that = (RulePreferenceMapping) o;
return new EqualsBuilder()
.append(rule, that.rule)
.append(rulePreference, that.rulePreference)
.isEquals();
}
@Override
public int hashCode()
{
return new HashCodeBuilder(17, 37)
.append(rule)
.append(rulePreference)
.toHashCode();
}
Rule.java расширяет AbstractEntity, которое является @ MappedSuperclass и содержит только одно свойство
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
protected Integer id;
@Override
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (o == null || getClass() != o.getClass())
{
return false;
}
AbstractEntity that = (AbstractEntity) o;
return new EqualsBuilder()
.append(id, that.id)
.isEquals();
}
@Override
public int hashCode()
{
return new HashCodeBuilder(17, 37)
.append(id)
.toHashCode();
}
Правило имеет другое отношение к RuleLevel.java (безтаблица соответствия, просто нормальное отношение 1 к N)
/**
* {@link RuleLevel} this {@link Rule} belongs to
*/
@ManyToOne(optional = false, fetch = FetchType.EAGER)
@JoinColumn(name = "rule_level_id")
private RuleLevel ruleLevel;
У меня есть встроенный HSQLDB для тестирования
- уровень правила
CREATE TABLE IF NOT EXISTS rule_level (
id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL,
name VARCHAR(255) NOT NULL,
updated TIMESTAMP NOT NULL,
PRIMARY KEY (id),
);
INSERT INTO rule_level (id, name, updated)
VALUES
(1, 'Country wide', current_timestamp),
(2, 'Department wide', current_timestamp),
(3, 'City wide', current_timestamp);
- правило
CREATE TABLE IF NOT EXISTS rule (
id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL,
name VARCHAR(255) NOT NULL,
information VARCHAR(512) NULL,
rule_level_id INT NULL,
updated TIMESTAMP NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (rule_level_id) REFERENCES rule_level(id),
);
INSERT INTO rule (id, name, information, rule_level_id, updated)
VALUES
(1, 'Rule 1', 'Information Rule 1', 1, current_timestamp),
(2, 'Rule 2', null, 1, current_timestamp),
(3, 'Rule 3', null, null, current_timestamp),
(4, 'Rule 4', 'Information Rule 4', null, current_timestamp);
- предпочтения правила
CREATE TABLE IF NOT EXISTS rule_preference (
id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL,
name VARCHAR(255) NOT NULL,
updated TIMESTAMP NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE IF NOT EXISTS rule_preference_mapping (
id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL,
rule_id INT NOT NULL,
rule_preference_id INT NOT NULL,
updated TIMESTAMP NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (rule_id) REFERENCES rule(id),
FOREIGN KEY (rule_preference_id) REFERENCES rule_preference(id),
INSERT INTO rule_preference (id, name, updated)
VALUES
(1, 'Preference 1', current_timestamp),
(2, 'Preference 2', current_timestamp),
(3, 'Preference 3', current_timestamp);
INSERT INTO rule_preference_mapping (id, rule_id, rule_preference_id, updated)
VALUES
(1, 1, 1, current_timestamp), -- set rule #1 to preference #1
(2, 2, 1, current_timestamp), -- set rule #2 to preference #1
(3, 3, 1, current_timestamp), -- set rule #3 to preference #1
(4, 1, 2, current_timestamp), -- set rule #1 to preference #2
(5, 2, 2, current_timestamp), -- set rule #2 to preference #2 **-- DON'T LOAD**
(6, 3, 2, current_timestamp); -- set rule #3 to preference #2 **-- DON'T LOAD**
Моя странная проблема заключается в том, что, пока мое правило имеет значение NULL, егоRuleLevel , из БД загружено только одно сопоставление с предпочтением.С этим набором данных мое Правило № 1 будет содержать 3 отображения предпочтений (идентификаторы 1, 2 и 3), но мое Правило № 2 будет содержать только сопоставление № 4.Два других просто не добавляются в набор.Конечно, я думал, что что-то происходит с моими equals () и hashCode (), но на самом деле это не так.
Пока я устанавливаю уровень для своего правила, он загружается, как и ожидалось.
Среда : Java8, Spring JPA с Hibernate