Hibernate @CollectionOfElements и @Parent - PullRequest
2 голосов
/ 24 декабря 2010

Я сделал следующее отображение:

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


}

И мой дао-тест:

@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} в мою встроенную сущность?Я не вижу, как это сделать, поскольку в моей встраиваемой сущности Picture не объявлено поле id

1 Ответ

0 голосов
/ 18 января 2011

Я не знаком с аннотацией @Parent для @Embeddable, но для «реальных» отношений всегда рекомендуется делать что-то вроде этого:

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

Помните, что ООП, в отличие отРеляционная модель имеет только понятие «односторонняя» навигация, и вы должны построить «двустороннюю» самостоятельно.Инкапсуляция этого поведения в установщике делает это прозрачным для ваших потребителей.Итак, я не уверен, почему ваш @Parent не работает, но я бы попытался сделать обратное:также его родительский объект был установлен на news2 ???

Ну, @Embeddable - это объект, который «встроен» в другой, что означает, что он принадлежит только этому другому объекту (родителю).Как таковой, он должен содержать только одного родителя.Если вы смените родителя, он будет принадлежать только этому новому родителю.Если вам нужен объект (Picture) для связи с другими объектами (News), вам понадобится @ManyToMany (если другой объект, News, также может быть связан с несколькими Picture)

...