0

I have two entities: Entry and Comment. One entry has n comments. I want to add extra lazy loading in my Entry for Comments. My entities looks like:

@Entity
@Table(name="entries")
public class Entry {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="id")
    private int id;

    @OneToMany(mappedBy = "entry", cascade = CascadeType.ALL, orphanRemoval = true)
    @LazyCollection(LazyCollectionOption.EXTRA)
    private List<Comment> comments = new ArrayList<>();

    public int getId() {
        return id;
    }

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

    public List<Comment> getComments() {
        return comments;
    }

    public boolean containsComment(int commentId) {
        return comments.contains(commentId);
    }

    public Comment getComment(int commentId) {
        return comments.get(commentId);
    }
}


@Entity
@Table(name="comments")
public class Comment {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    public int id;

    @ManyToOne
    private Entry entry;

    public int getId() {
        return this.id;
    }

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

    public Entry getEntry() {
        return entry;
    }

    public void setEntry(Entry entry) {
        this.entry = entry;
    }
}

I wrote a test to test the association mapping:

@Test
@Transactional
public void testContainsComment() {
    /* I inserted already an entry and a comment for the entry into the database */
    Entry entry = entryDao.getById(1);
    boolean containsComment = entry.containsComment(1); // -> Here I get the following exception: org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [public int com.mypackage.Comment.id] by reflection for persistent property [com.mypackage.Comment#id] : 1
    Assert.assertTrue(containsComment);
}

Why I get the following exception?

org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [public int com.mypackage.Comment.id] by reflection for persistent property [com.mypackage.Comment#id] : 1

What did I missed?

Additional Info I should mention that I can access the comments collection with the getComments() method. The size() on the comments collection works too. The single problem is the contains() method. Note that I pass the commentId as parameter to the containsComment()-method. Can / Should I pass something else?

The funny thing is that hibernate logs the right query for the contains method.

Hibernate: select 1 from comments where entry_id =? and id =?
kemal89
  • 931
  • 2
  • 8
  • 20
  • What exactly is your question asking? You show your code, and you show the output, but you never specifically state where the problem is. – Lilith Daemon Apr 10 '16 at 19:17
  • The exception is the problem :) – kemal89 Apr 10 '16 at 20:03
  • I should mention that I can access the comments collection with the getComments() method. The size() on the comments collection works too. The single problem is the contains() method. Note that I pass the commentId as parameter to the containsComment()-method. Can / Should I pass something else? – kemal89 Apr 11 '16 at 07:11

3 Answers3

2

You use the method comments.contains() in the incorrect way.

private List<Comment> comments = new ArrayList<>();

comments is a List of Comment, so you need to pass a Comment to the contains() method

comments.contains(new Comment(1))

Obviously, this code find nothing, because of, contains() uses equals (by reference, in this case) to check equality of objects. You can override equals() and hashCode() of Comment to get a valid behavior.

Or you can use a loop and check id equality element by element, or use a temporary set with ids, if you need to check a lot of comments, or query a database for checking particular Comment id.

v.ladynev
  • 19,275
  • 8
  • 46
  • 67
1

add setter your Entry.class property comments setter not added

add this in Entry.class

public List<Comment> setComments(List<Comment> comments) {
        this.comments = comments;
    }

Edit refactor containsComment method like this

public boolean containsComment(int commentId) {

       for(Comment comment : getComments()){
          if(comment.getId() == commentId){
             return true;
          } }       
         return false;
    }
kakashi hatake
  • 1,175
  • 2
  • 10
  • 18
  • Unfortunately this did not help. Did it help in your case? Can you show me some code? – kemal89 Apr 11 '16 at 07:08
  • I should mention that I can access the comments collection with the getComments() method. The size() on the comments collection works too. The single problem is the contains() method. Note that I pass the commentId as parameter to the containsComment()-method. Can / Should I pass something else? – kemal89 Apr 11 '16 at 07:11
  • It is incorrect. `getComments()` returns a `List`, it doesn't have `getId()` method! – v.ladynev Apr 11 '16 at 08:01
  • I would take this answer a step further by refactoring the `containsComment()` method out of the entity into a separate class to keep things easy to test. – Saïd Apr 11 '16 at 08:24
  • @Saheed yes ,not good choice in entity class use logic, I was carrying this method into a class with private access – kakashi hatake Apr 11 '16 at 08:29
  • You can use entity based logic in the entity. Otherwise the entities would be simple data objects without responsibility. – kemal89 Apr 11 '16 at 08:50
  • @user3481997 yes you can use it's possible but not good choice for single responsibility principle – kakashi hatake Apr 11 '16 at 08:53
0

try this:

on Comment class, after @ManyToOne, specify a @JoinColumn like:

@JoinColumn(name = "id")

Check also this post.

Community
  • 1
  • 1
alexandrum
  • 429
  • 9
  • 17
  • No, still got the same exception. – kemal89 Apr 10 '16 at 20:58
  • I should mention that I can access the comments collection with the getComments() method. The size() on the comments collection works too. The single problem is the contains() method. Note that I pass the commentId as parameter to the containsComment()-method. Can / Should I pass something else? – kemal89 Apr 11 '16 at 07:11
  • 1
    if `mappedBy` is used, Hibernate uses implicitly `@JoinColumn`. But it is a good practice to specify `@JoinColumn` explicity. – v.ladynev Apr 11 '16 at 07:59