java - hibernate @CollectionOfElements 和@Parent

标签 java hibernate jpa jakarta-ee parent-child

我完成了以下映射:

@Entity
@Table(name = "NWS_NEWS")
public class News implements Serializable {

    private static final long serialVersionUID = 5246618151933389186L;

    private String id;
    private List<Picture> pictures;

    + OTHER fields / getters / setters, no matter

    @Id
    @GeneratedValue(generator = "juuid")
    @Column(length = 36)
    public String getId() {
        return id;
    }


    @CollectionOfElements
    @JoinTable(name = "NWS_PICTURES",joinColumns = @JoinColumn(name="NEWS_ID"))
    @CollectionId(
            columns= @Column(name="PICTURE_ID"),
            type=@Type(type="long"),
            generator="sequence")
    public List<Picture> getPictures() {
        return pictures;
    }

    public void setPictures(List<Picture> pictures) {
        this.pictures = pictures;
    }



}

我的照片是:

@Embeddable
public class Picture implements Serializable {

    private static final long serialVersionUID = -1397366206984323622L;

    private News news;

    private String path;

    private ImageSize imageSize;


    @Parent
    public News getNews() {
        return this.news;
    }

    @Column(name = "path", nullable=false)
    public String getPath() {
        return path;
    }

    @Enumerated(EnumType.STRING)
    @Column(name = "size", nullable=false)
    public ImageSize getImageSize() {
        return imageSize;
    }


    public void setImageSize(ImageSize imageSize) {
        this.imageSize = imageSize;
    }
    public void setNews(News news) {
        this.news = news;
    }
    public void setPath(String path) {
        this.path = path;
    }


}

我的 dao 测试是:

@Test
public void testAddPicturesToNews() {

    News newsToSave = new News();
    // Create big picture
    Picture pBig = new Picture();
    pBig.setImageSize(ImageSize.BIG);
    pBig.setPath("/tmp/blabla_big.jpg");
    // Create medium picture
    Picture pMedium = new Picture();
    pMedium.setImageSize(ImageSize.MEDIUM);
    pMedium.setPath("/tmp/blabla_med.jpg");
    // Set the pictures in the news
    List<Picture> picturesList = new ArrayList<Picture>();
    picturesList.add(pBig);
    picturesList.add(pMedium);
    newsToSave.setPictures(picturesList);
    // Save the news
    this.newsDAO.saveOrUpdate(newsToSave);
    String newsId = newsToSave.getId();
    News newsLoaded = this.newsDAO.findById(newsId);
    List<Picture> picturesLoaded = newsLoaded.getPictures();
    for ( Picture pictureLoaded : picturesLoaded ) {
        System.out.println(pictureLoaded.getPath());
        System.out.println(pictureLoaded.getImageSize());
        System.out.println(pictureLoaded.getNews());
        System.out.println("\n");
    }

}

但是输出是:

/tmp/blabla_big.jpg
BIG
null


/tmp/blabla_med.jpg
MEDIUM
null

其实我不明白为什么 getNews() 在子实体实体中返回 null,而它有“@Parent”注解。难道我做错了什么?

无论如何,让父实体成为子实体的概念对我来说似乎有点奇怪,因为如果我这样做会发生什么:

News news1 = new News();
News news2 = new News();
List<Picture> picList = new ArrayList<Picture>();
Picture picture1 = new Picture();
picturesList.add(picture1);
picture1.setNews(news2);
news1.setPictures(picList);
this.newsDAO.saveOrUpdate(news1);
this.newsDAO.saveOrUpdate(news2);

如果同一张图片将出现在 news1 列表中,而且其父级设置为 news2,会发生什么情况???

我想我会没有那个 parent ,我不需要那么多,但这只是好奇...... 谢谢

顺便说一句,我希望每个新闻只有一张图片 -> 同一条新闻不能有 2 张小图片。 那么是否可以在我的嵌入式实体中对 {news_id , imageSize} 添加唯一约束?我不知道该怎么做,因为在我的图片可嵌入实体中没有声明 id 字段

最佳答案

我不熟悉 @Embeddable 的 @Parent 注释,但对于“真实”关系,总是建议这样做:

// News class
public void setPictures(List<Picture> pictures) {
  this.pictures = pictures;
  for (Picture picture : pictures) {
    picture.setNews(this);
  }
}

public void addPicture(Picture picture) {
  this.pictures.add(picture);
  picture.setNews(this);
}

请记住,与关系模型相反,OOP 只有“单向”导航的概念,您应该自己构建“双向”导航。将此行为封装在 setter 中会使它对您的消费者透明。所以,我不确定为什么你的@Parent 不起作用,但我会尝试做相反的事情:

// what you have:
newsToSave.setPictures(picturesList);

// what I'd try:
pMedium.setNews(newsToSave);

What would happen since the same picture will be in news1 list, but also its parent was set to news2???

好吧,@Embeddable 是一个“嵌入”到另一个对象中的对象,这意味着它只属于另一个对象(父对象)。因此,它应该只包含一个父级。如果您更改父级,它将只属于这个新父级。如果您需要一个对象 (Picture) 与其他对象 (News) 建立关系,您将需要一个 @ManyToMany(如果另一个对象是 News ,也可能链接到几张图片)

关于java - hibernate @CollectionOfElements 和@Parent,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4525789/

相关文章:

java - Hibernate @ManyToOne 调用自身

java - 大规模处理以在非常大的字符串列表中找到唯一的最长单词?

java - 创建和访问 Vector 类

java - Hibernate Apache Derby 自定义序列

java - Spring 使用@Validated 验证 Controller

java - Spring 无法注入(inject)实体管理器工厂

java - jpa中的范围查询

java - 如何使用 Selenium WebDriver 在 Chrome 中激活 AdBlocker?

java.lang.ClassCastException : android. 部件.ExpandableListView$ExpandableListContextMenuInfo

java - 如何保存具有现有子对象的对象?