@ManyToOne and @OneToOne relations with @EmbeddedId
Sequencing shouldn't be used if you want a composite pk - use only the sequence generated field which is unique, or composite business fields that are unique.
Second issue is the joinColumn definitions in User. You have marked them as updatable=false, insertable=false which means the foreign keys cannot be changed through the mappings, and is why they are always null regardless of setting the relationship. Remove the updatable=false, insertable=false settings from each to have the fields set when you set the relationship.
Andreas Lenggenhager
Updated on June 04, 2022Comments
-
Andreas Lenggenhager almost 2 years
I am trying to change the id of my database entities from a single long to a composite id consisting of two long's which are encapsulated in my ID.class shown below. What annotations would you use for ManyToOne and OneToMany relations? Did I made a mistake with my annotations, especially with @JoinColumns, @Embeddable and @EmbeddedId. My problem is that relations are stored with null;
My ID class consist of an autogenerated long (pid) and a manually set secondary long (sid). This is the ID for all my entity classes:
@Embeddable public class ID implements Serializable { @GeneratedValue(strategy = GenerationType.SEQUENCE) private long pid; @Column(nullable=false) private long sid; }
My Entity-class (example) has a many-to-one relation to Office a one-to-one relation to Settings (both relations are uni-directional).
@Entity @Table(name="user") public class User { @EmbeddedId private ID id; @ManyToOne(fetch=FetchType.LAZY) @JoinColumns({ @JoinColumn(name = "office_pid", referencedColumnName = "pid", updatable=false, insertable=false), @JoinColumn(name = "office_sid", referencedColumnName = "sid", updatable=false, insertable=false) }) private Office office; @OneToOne(cascade={CascadeType.PERSIST, CascadeType.REMOVE}, fetch=FetchType.LAZY) @JoinColumns({ @JoinColumn(name = "setting_pid", referencedColumnName = "pid", updatable=false, insertable=false), @JoinColumn(name = "setting_sid", referencedColumnName = "sid", updatable=false, insertable=false) }) private Settings setting; @OneToMany(mappedBy = "user", cascade=CascadeType.REMOVE, fetch=FetchType.LAZY) private List<Account> accounts= new ArrayList<>(); }
Office class (Many-To-One example):
@Entity @Table(name = "office") public class Office { @EmbeddedId private ID id; @Column(length = 128) private String description; }
Account class (One-To-Many example):
@Entity @Table(name="account") public class Account { @EmbeddedId private ID id; @Column(length = 16) private String description; @ManyToOne(fetch=FetchType.LAZY) @JoinColumns({ @JoinColumn(name = "user_pid", referencedColumnName = "pid"), @JoinColumn(name = "user_sid", referencedColumnName = "sid") }) private User user; }
Thanks in advance for your help.
-
Andreas Lenggenhager over 9 yearsThanks for your fast reply. I removed all updatable=false and insertable=false and I looks promising. But now I am stucked with the @OneToMany relations. What annotation do I need there?
-
Andreas Lenggenhager over 9 yearsFor now, I am not changing the sequencing as it works pretty well for me.
-
Chris over 9 yearsSorry, I'm not sure what you mean when you say you are stuck with @OneToMany relations. You were using ManyToOne and OneToOne in the code - changing the insertable, updatable flags does not mean you need to change your mappings unless you had those fields mapped through another mapping as well.
-
Andreas Lenggenhager over 9 yearsMy entites also have @OneToMany as well. I didn't mentioned it because I thought it works. But I was wrong. I updated the code in my first post with an example of an OneToMany relation.
-
Chris over 9 yearsThere is nothing wrong with the OneToMany mapping shown. My guess now is that you have a bidirectional relationship and are making the common mistake of only setting one side. When you update the Account.user, you must also add that account to the user.accounts list