31

I have these tables:

tables

Which my intention is : A user can be a company or a person but each one of them have something in common, as username which is the email and password, so I used the JPA Tools to generate the entities from the table which result on this:

public class User implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int id;

    private String email;

    private String password;

    private int reputation;

    //bi-directional one-to-one association to Company
    @OneToOne(mappedBy="user", cascade={CascadeType.ALL})
    private Company company;

    //bi-directional many-to-one association to Location
    @OneToMany(mappedBy="user")
    private List<Location> locations;

    //bi-directional one-to-one association to Person
    @OneToOne(mappedBy="user")
    private Person person;

    //bi-directional many-to-one association to Product
    @OneToMany(mappedBy="user")
    private List<Product> products;

    //bi-directional many-to-one association to UserType
    @ManyToOne
    @JoinColumn(name="type")
    private UserType userType;

    //bi-directional many-to-one association to UserPhone
    @OneToMany(mappedBy="user")
    private List<UserPhone> userPhones;

    //bi-directional many-to-one association to UserPicture
    @OneToMany(mappedBy="user")
    private List<UserPicture> userPictures;

    //bi-directional many-to-one association to UserSocialNetwork
    @OneToMany(mappedBy="user")
    private List<UserSocialNetwork> userSocialNetworks;

        // getter and setters

}

Now if I try to persist an user object launchs the follow exception in EclipseLink:

Exception [EclipseLink-48] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Multiple writable mappings exist for the field [COMPANY.id_user].  Only one may be defined as writable, all others must be specified read-only.
Mapping: org.eclipse.persistence.mappings.OneToOneMapping[user]
Descriptor: RelationalDescriptor(entity.Company --> [DatabaseTable(COMPANY)])
Exception [EclipseLink-48] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Multiple writable mappings exist for the field [PERSON.id_user].  Only one may be defined as writable, all others must be specified read-only.
Mapping: org.eclipse.persistence.mappings.OneToOneMapping[user]
Descriptor: RelationalDescriptor(entity.Person --> [DatabaseTable(PERSON)])
Runtime Exceptions: 

Is the generated mapping wrong ? How can I solve this exception ?

Update

public class Company implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="id_user")
    private int idUser;

    private String email;

    private String name;

    //bi-directional many-to-one association to Area
    @ManyToOne
    @JoinColumn(name="area")
    private Area areaBean;

    //bi-directional one-to-one association to User
    @OneToOne(cascade={CascadeType.ALL})
    @JoinColumn(name="id_user", insertable=false, updatable=false)
    private User user;

        // getter and setters
}

@Entity
public class Person implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="id_user")
    private int idUser;

    @Temporal( TemporalType.DATE)
    private Date birthdate;

    private String gender;

    private String name;

    private String surname;

    //bi-directional one-to-one association to User
    @OneToOne
    @JoinColumn(name="id_user", insertable=false, updatable=false)
    private User user;

        // getters and setters
}
Valter Silva
  • 16,446
  • 52
  • 137
  • 218

3 Answers3

42

I solved my problem placing the insertable=false, updatable=false in the @JoinColumn annotation in both classes, Person and Company.

giannis christofakis
  • 8,201
  • 4
  • 54
  • 65
Valter Silva
  • 16,446
  • 52
  • 137
  • 218
39

The proper way to do this is to use @PrimaryKeyJoinColumn instead of plain old @JoinColumn.

reference wiki example on PrimaryKeyJoinColumn

shareef
  • 9,255
  • 13
  • 58
  • 89
klonq
  • 3,535
  • 4
  • 36
  • 58
  • I had a table with only one column which was a subset of the the ids of another table. This solved it for me. – Mr_and_Mrs_D Feb 15 '14 at 17:57
  • Hello, team! It's help me. My JSF application use ralation ONE to MANY between Customers(ID) and Comments(CUSTID) tables I switch @JoinColumn(name="ID", referencedColumnName="CUSTID") to @PrimaryKeyJoinColumn(name="ID", referencedColumnName="CUSTID") – Mikro Koder Mar 16 '17 at 20:37
4

My guess is that you have the id_user mapped twice, once using a Basic @Id mapping, and once using the @ManyToOne. You need to make one of them read-only, i.e. insertable/updatable=false. Or better, just remove the basic id, and put the @Id on the @ManyToOne.

See, http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing#Primary_Keys_through_OneToOne_and_ManyToOne_Relationships

James
  • 17,965
  • 11
  • 91
  • 146
  • upvoted because a reference is provided. I suggest that you also mention '@PrimaryKeyJoinColumn' in your answer – S. Pauk Apr 28 '15 at 08:27