4

I have entity with composite Id

@Entity
@IdClass(value = BorrowId.class)
@Table(name = "BORROW")
public class Borrow {

    @Id
    @Column(name = "BOOK_ID", insertable = false, updatable = false)
    private long bookId;

    @Id
    @Column(name = "BORROWER_ID", insertable = false, updatable = false)
    private long borrowerId;

    @Id
    @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
    @JoinColumn(name = "BOOK_ID")
    private Book book;

    @Id
    @ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
    @JoinColumn(name = "BORROWER_ID")
    private Borrower borrower;

    @Id
    @Column(name = "BORROW_DATE")
    private Date borrowDate;

    @Column(name = "RETURN_DATE")
    private Date returnDate;

BorrowId has properties (everything with getters/setters)

    private long bookId;
    private long borrowerId;

    private Date borrowDate;

and equals,hashCode methods

when I'm trying to persist Borrow entity (book and borrower properties set to corresponding entities, then calling entityManager.persist(borrow); ) I've got in my logs:

Hibernate: insert into BORROW (BORROWER_ID, BOOK_ID, RETURN_DATE, BORROW_DATE) values (?, ?, ?, ?) // this insert statement is correct (that's a look of my table) Invalid value "5" for parameter "parameterIndex" [90008-174]

So it looks like someone is doing something wrong :) How to solve this? is my entity declaration faulty? (I wanted to use CompositeId to learn something about using it)

Andrea Ligios
  • 49,480
  • 26
  • 114
  • 243
razor
  • 2,727
  • 6
  • 33
  • 45
  • 1
    The mapping is wrong, and you're making your own life difficult by having such complex composite IDs. Follow the best practices and use a single-column autogenerated ID. Everything will be much easier, in all layers of the app, and also faster and cleaner. – JB Nizet Nov 22 '13 at 13:40
  • As i said, i want to use composite Id to know something about it (it's not a production app). What's wrong with mappings ? this mapping creates correct tables in DB (borrow with only 4 columns), reads data from it correctly too, but it can't persist a new Borrow – razor Nov 22 '13 at 14:07
  • 3
    The properties annotated with `@Id` must match with the properties in the ID class. book and borrower should not be annotated with `@Id`, but with `@MapsId`. See http://docs.jboss.org/hibernate/core/4.2/manual/en-US/html_single/#d5e2309 – JB Nizet Nov 22 '13 at 14:13
  • Thanks, `@MapsId` on Borrower and Book entites solves the problem. I didn't tried it, because it's nowhere used in examples with `@IdClass` (only with `@EmbeddedId`). If these examples even work then ? – razor Nov 22 '13 at 14:27

1 Answers1

2

Thanks to @JB nizet

@Id
@Column(name = "BOOK_ID", insertable = false, updatable = false)
private long bookId;

@Id
@Column(name = "BORROWER_ID", insertable = false, updatable = false)
private long borrowerId;

@MapsId("bookId")
@ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST,
                                              CascadeType.MERGE,
                                              CascadeType.REFRESH})
@JoinColumn(name = "BOOK_ID")
private Book book;

@MapsId("borrowerId")
@ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, 
                                               CascadeType.MERGE,
                                               CascadeType.REFRESH})
@JoinColumn(name = "BORROWER_ID")
private Borrower borrower;

@Id
@Column(name = "BORROW_DATE")
private Date borrowDate;

Solves the problem, strange, because nowhere, in any example/tutorial there was no @MapsId used with @IdClass. I'm not sure if now @JoinColumn is needed

mkobit
  • 43,979
  • 12
  • 156
  • 150
razor
  • 2,727
  • 6
  • 33
  • 45