【问题标题】:Composite key doesn't get populated by corresponding ID复合键不会由相应的 ID 填充
【发布时间】:2017-10-12 09:08:17
【问题描述】:

这里是CampaignEntity.class 实体:

@Entity
@Table(name = "campaign")
public class CampaignEntity implements Serializable {

    @Id
    @SequenceGenerator(name = "campaign_id_gen", sequenceName = "campaign_seq", initialValue = 1, allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "campaign_id_gen")
    private Long id;

    @OneToMany(cascade = CascadeType.REMOVE, mappedBy = "campaignId", fetch = FetchType.EAGER, targetEntity = CampaignCountry.class)
    private List<CampaignCountry> countries;

    @Column(name = "include_countries")
    private Boolean includeCountries;

    // getters & setters, toString, hashEquals
}

这是我正在尝试映射的CampaignCountry.class

@Entity
@Table(name = "campaign_country")
@IdClass(CampaignCountry.CampaignCountryPK.class)
public class CampaignCountry {
    @Id
    @Column(name="campaign_id")
    private Long campaignId;
    @Id
    @Column(name="country")
    private String country;

    public CampaignCountry(String country) {
        this.country = country;
    }

    //getters and setters

    static class CampaignCountryPK implements Serializable {

        private Long campaignId;

        private String country;

        public CampaignCountryPK() {}

        public CampaignCountryPK(Long campaignId, String country) {
            this.campaignId = campaignId;
            this.country = country;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            CampaignCountryPK that = (CampaignCountryPK) o;

            if (campaignId != null ? !campaignId.equals(that.campaignId) : that.campaignId != null) return false;
            return country != null ? country.equals(that.country) : that.country == null;
        }

        @Override
        public int hashCode() {
            int result = campaignId != null ? campaignId.hashCode() : 0;
            result = 31 * result + (country != null ? country.hashCode() : 0);
            return result;
        }
    }
}

当我打电话给repository.saveAndFlush(campaignEntity) 时,问题就来了。它可以根据需要保存国家/地区,但不能保存 CampaignId。它始终为空。

org.springframework.orm.jpa.JpaObjectRetrievalFailureException:Unable to find domain.CampaignCountry with id domain.CampaignCountry$CampaignCountryPK@e43;

嵌套异常是 javax.persistence.EntityNotFoundException: Unable to find domain.CampaignCountry with id domain.CampaignCountry$CampaignCountryPK@e43

这是迁移 SQL 脚本(如果它与任何事情有关):

CREATE TABLE campaign_country (
  campaign_id BIGINT               NOT NULL,
  country     CHARACTER VARYING(2) NOT NULL,
  PRIMARY KEY (campaign_id, country)
);

ALTER TABLE campaign_country
  ADD CONSTRAINT campaign_to_campaign_country FOREIGN KEY (campaign_id) REFERENCES campaign (id);

那么这里出了什么问题,我如何用相应的活动实体的 ID 填充活动 ID?我确实相信它有一些 @OneToMany 注释,它可能没有正确实现。

【问题讨论】:

  • 尝试使用@OneToMany(cascade = CascadeType.ALL, mappedBy = "campaignId", fetch = FetchType.EAGER, targetEntity = CampaignCountry.class)
  • 实体类看起来很奇怪,你是怎么创建的?
  • @juvenislux 没有帮助。仍然为空。

标签: java hibernate jpa hibernate-mapping


【解决方案1】:

改用@EmbeddedId 怎么样?

@Entity
public class CampaignCountry implements Serializable {

    @EmbeddedId
    private CampaignCountryPK id;

    @MapsId("campaignId")
    @ManyToOne
    @JoinColumn(name = "campaign_id")
    private CampaignEntity campaignEntity;
}

@Embeddable
public class CampaignCountryPK implements Serializable {

    @Column(name = "campaign_id")
    private long campaignId;
    @Column(name = "country")
    private String country;
}

@Entity
@Table(name = "campaign_country")
public class CampaignCountry implements Serializable {

    @EmbeddedId
    private CampaignCountryPK id;

    @MapsId("campaignId")
    @ManyToOne
    @JoinColumn(name = "campaign_id")
    private CampaignEntity campaignEntity;
}

然后在CampaignEntity 中将映射改为:

@OneToMany(cascade = CascadeType.ALL, mappedBy = "campaignEntity", fetch = FetchType.EAGER, targetEntity = CampaignCountry.class)
private List<CampaignCountry> countries;

您只需将对象创建为:

List<CampaignCountry> countryList = new ArrayList<>();
CampaignEntity campaign = new CampaignEntity();

CampaignCountryPK pk1 = new CampaignCountryPK();
pk1.setCountry("Country 1");
CampaignCountry country1 = new CampaignCountry();
country1.setId(pk1);
country1.setCampaignEntity(campaign);

countryList.add(country1);
campaign.setCountries(countryList);

或者您可以创建一个创建 PK 的方法。

【讨论】:

  • 我照你说的做了。映射@MapsId 时引用实体上的意外标识符类型:com.newagesol.promotion.domain.CampaignEntity
  • includeCountries 是 db 列吗?如果不是,您尝试将其标记为@Transient
  • 是的。我刚刚检查过了。
  • 什么意思?如果是列,则打上必要的注解,否则标记为@Transient或删除
  • 完成。但是默认情况下 Hibernate 会为该类生成列。这与我的错误无关。这就是我的意思。
猜你喜欢
  • 1970-01-01
  • 2014-06-08
  • 1970-01-01
  • 2012-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多