JPA关系仅部分加载

时间:2019-02-11 07:48:22

标签: java hibernate jpa orm

我有两个通过映射表将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扩展了 @MappedSuperclass 的AbstractEntity,并且仅包含一个属性

@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();
}

Rule与 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**

我的怪异问题是,只要我的Rule的RuleLevel值为 NULL ,就只能从DB加载到首选项的一个映射。 对于此数据集,我的Rule#1将包含3个首选项映射(标识1、2和3),但是我的Rule#2将仅包含映射4。其他两个根本不会添加到集合中。我当然认为我的equals()和hashCode()发生了什么,但实际上没有。

只要我为规则设置一个级别,它就会按预期加载。

环境:Java8,带有Hibernate的Spring JPA

0 个答案:

没有答案