Hibernate @CollectionOfElements 和 @Parent

发布于 2024-10-09 09:28:58 字数 3576 浏览 0 评论 0原文

我已经完成了以下映射:

@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 ,会发生什么? ??

我想我会不需要那个父母,我不需要那么多,但这只是好奇心...... 谢谢

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

I've done the following mapping:

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



}

And my picture is:

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


}

And my dao test is:

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

}

But the output is:

/tmp/blabla_big.jpg
BIG
null


/tmp/blabla_med.jpg
MEDIUM
null

Actually i don't understand why getNews() returns null in the child entity entity, while it has the "@Parent" annotation. Am i doing something wrong?

Anyway the concept of getting the parent in a child entity seems a bit strange for me since what would happen if i do something like that:

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);

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

I think i'll do without that parent, i don't need that so much but it's just curiosity...
Thanks

Btw i'd like to have only one picture of each size for a news -> there can't be 2 small pictures for the same news.
So is it possible to add a unique constraint on {news_id , imageSize} in my embedded entity? I don't see how to do that since no id field is declared in my Picture embeddable entity

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

凡间太子 2024-10-16 09:28:58

我不熟悉 @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);

由于同一张图片将出现在 news1 列表中,但其父级也设置为 news2 ,会发生什么???

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

I'm not familiar with the @Parent annotation for an @Embeddable, but for "real" relationships it's always recommended to do something like this:

// 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);
}

Remember that OOP, as opposed to the relational model, has only the notion of a "one-way" navigation, and that you should build the "two-way" by yourself. Encapsulating this behavior in the setter makes this transparent to your consumers. So, I'm not sure why your @Parent is not working, but I would try to do the opposite:

// 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???

Well, an @Embeddable is an object which is "embedded" into another, meaning that it belongs only to that other object (parent). As such, it should contain only one parent. If you change the parent, it'll belong only to this new parent. If you need an object (Picture) to have a relationship with other objects (News), you'll need a @ManyToMany (if the other object, News, may also be linked to several Picture)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文