Hibernate Books

All times are UTC - 5 hours [ DST ]



Post new topic Reply to topic  [ 2 posts ] 
Author Message
 Post subject: ManyToMany mapping, SpringBoot, PostgreSQL
PostPosted: Sun Feb 12, 2017 7:48 am 
Newbie

Joined: Sun Feb 12, 2017 7:37 am
Posts: 1
Trying to map correctly two simple classes:
1. News class:
Code:
@Entity(name = "news")
public class News implements Serializable {
    private Long id;
    private Date date;
    private String text;
    private String author;
    private Set<HashTag> hashTags = new HashSet<HashTag>(0);
    private byte[] image;

    public News() {
    }

    public News(Date date, String text, String author, Set<HashTag> hashTags, byte[] image) {
        this.date = date;
        this.text = text;
        this.author = author;
        this.hashTags = hashTags;
        this.image = image;
    }

    @Id
    @Column(name = "news_id", nullable = false)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "NewsIDGenerator")
    @SequenceGenerator(name = "NewsIDGenerator", sequenceName = "SEQ_NEWS_ID")
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Temporal(TemporalType.DATE)
    @DateTimeFormat(pattern = "DD/MM/YYYY")
    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    @Lob
    @Type(type = "org.hibernate.type.TextType")
    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @Column(name = "hashTags")
    @JoinTable(name = "news_hashTag",
            joinColumns = @JoinColumn(name = "news_id", nullable = false),
            inverseJoinColumns = @JoinColumn(name = "hashtag_id", nullable = false))
    public Set<HashTag> getHashTags() {
        return hashTags;
    }

    public void setHashTags(Set<HashTag> hashTags) {
        for (HashTag hashTag: hashTags) {
            hashTag.addNews(this);
        }
        this.hashTags = hashTags;
    }

    @Lob
    public byte[] getImage() {
        return image;
    }

    public void setImage(byte[] image) {
        this.image = image;
    }
}


2. HashTag class:
Code:
@Entity(name = "hashTag")
public class HashTag implements Serializable {
    private Long id;

    private String name;
    private Set<News> news = new HashSet<News>(0);

    public HashTag() {
    }

    public HashTag(String name) {
        this.name = name;
    }

    @Id
    @Column(name = "hashtag_id", nullable = false)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "HashTagIDGenerator")
    @SequenceGenerator(name = "HashTagIDGenerator", sequenceName = "SEQ_HASHTAG_ID")
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @ManyToMany(fetch = FetchType.LAZY, mappedBy = "hashTags")
    @Column(name = "news")
    public Set<News> getNews() {
        return news;
    }

    public void setNews(Set<News> news) {
        this.news = news;
    }
}


I'm constructing RESTful API, so I ping my controller with Json like that:
Code:
{
   "text": "Unbelievable news!",
   "author": "Unknown",
   "hashTags": [
      {
         "name": "hashTag_1"
      },
      {
         "name": "hashTag_2"
      }
      ]
}


My method of controller which creates new news:

Code:
   @RequestMapping(method = RequestMethod.POST, produces = {"application/json"}, consumes = {"application/json"})
    @ResponseStatus(HttpStatus.OK)
    public @ResponseBody String addNews(@RequestBody String jsonString) {
        if (LoggedUser.isAdmin()) {
            News news = new News(jsonString);
            if (news.getText() != null) {
                if (news.getDate() == null) {
                    news.setDate(new Date());
                }
                news.setHashTags(news.getHashTags()); // just set for each hashTag link to news
                newsService.save(news);
                return news.toJson();
            }
        }
        return null;
    }


And I got error message:
Quote:
Hibernate:
select
nextval ('seq_news_id')
Hibernate:
select
nextval ('seq_hashtag_id')
Hibernate:
insert
into
news
(author, date, image, text, news_id)
values
(?, ?, ?, ?, ?)
Hibernate:
insert
into
hash_tag
(name, hashtag_id)
values
(?, ?)
2017-02-12 14:16:23.309 WARN 48770 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: 23502
2017-02-12 14:16:23.309 ERROR 48770 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : ERROR: null value in column "news_id" violates not-null constraint
.о.ро.ност.: Failing row contains (250, null, hashTag_1, null).


What I'm doing wrong?


Top
 Profile  
 
 Post subject: Re: ManyToMany mapping, SpringBoot, PostgreSQL
PostPosted: Sun Feb 12, 2017 10:09 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1527
There are many issues:

1. This line makes no sense:

Code:
news.setHashTags(news.getHashTags()); // just set for each hashTag link to news


Why would you call the setter with the result of the same getter?

2. You need to synchronize both ends of the association. Better use a method like this one:

Code:
public void addHashTags(HashTag hashTag) {
        hashTag.addNews(this);
        this.hashTags.add(hashTag);
}


3. In this mapping:

Code:
    @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @Column(name = "hashTags")
    @JoinTable(name = "news_hashTag",
            joinColumns = @JoinColumn(name = "news_id", nullable = false),
            inverseJoinColumns = @JoinColumn(name = "hashtag_id", nullable = false))
    public Set<HashTag> getHashTags() {
        return hashTags;
    }


Why do you use the @Column(name = "hashTags") since you already have a @JoinTable?

The issue here is that the news_id is null, which odd because is auto generated.

_________________
If you liked my answer, you are going to love my High-Performance Java Persistence book and my blog as well.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.