MappedBy in a OneToOne Mapping

13,279

Solution 1

In your code, user-user_subscription looks uni-directional. 'mappedby' should be used in bi-directional relationship.

You can use following code in user entity to make it bi-directional with user_subscription.

private UserSubscription userSubscription; 
@OneToOne
    public User getUserSubscription() {
        return userSubscription;
    }

Or remove mappedby from user_subscription and make it unidirectional.

Solution 2

Seems you are unsure of what mappedBy is used for or means. Database relationships are one sided; one table will have a foreign key reference to the target table. In JPA, you might map this relationship as a OneToOne and specify the foreign key to use with the @JoinColumn annotation:

@OneToOne(mappedBy="userId")
@JoinColumn(name = "USER_ID")
public User getUser() {
    return user;
}

The Join column definition is optional, and if not used JPA will default to using the attribute name with "_" and the target entity's ID name prepended, so "USER_ID" in this case anyway.

Back to the database, because target table is referenced by the source table, this forms another implicit relationship back (the target table's ID can be used to look up the other table's foreign key). In JPA, this can be mapped again as a OneToOne or a OneToMany depending on the cardinality. If it is a OneToOne, you specify that this relationship does not define the foreign key by marking it as mappedBy the other relationship:

@OneToOne(mappedBy="user")
public UserSubscription getUserSubscription() {
    return userSubscription;
}

But it is more likely a User will have multiple userSubscriptions:

@OneToMany(mappedBy="user")
public Collection<UserSubscription> getUserSubscriptions () {
    return userSubscription ;
}

In both cases, you use the mappedBy to signal that there is a 'user' attribute in the target entity that defines a relationship to this entity and controls the foreign key setting in the database.

You also need to change how your define the UserSubscription->Subscription relationship, as you have defined an @Column on what appears to be a relationship. It should probably be

@OneToOne
@JoinColumn(name="Subscription_Id")
public Subscription getSubscription() {
    return subscription;
}
Share:
13,279
M. Shariq
Author by

M. Shariq

Updated on June 21, 2022

Comments

  • M. Shariq
    M. Shariq almost 2 years

    I have created Three classes- User, UserSubscription and Subscription. I want that users in the UserSubscription table should be referenced by the users existing in the User table. So, how to use mappedBy? The classes are as follows:

    User:

        package com.model;
    
        import java.util.HashSet;
        import java.util.Set;
    
        import javax.persistence.CascadeType;
        import javax.persistence.Column;
        import javax.persistence.Entity;
        import javax.persistence.FetchType;
        import javax.persistence.GeneratedValue;
        import javax.persistence.Id;
        import javax.persistence.JoinColumn;
        import javax.persistence.JoinTable;
        import javax.persistence.ManyToMany;
        import javax.persistence.OneToOne;
    
        @Entity
        public class User {
    
    
        private int userId;
        private String password;
        private String contact;  
        private String firstName;
        private String lastName;
        private String gender;
        private String address;
        private int age;
        private String email;
        private String countBooks;
    
    
        private Set<Language> languages = new HashSet<Language>(0);
        private Set<Book> favorites = new HashSet<Book>(0);
    
    
        @Id
        @GeneratedValue
        @Column(name="User_Id")
        public int getUserId() {
            return userId;
        }
    
        public void setUserId(int userId) {
            this.userId = userId;
        }
    
        @Column(name="Password")
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
    
        @Column(name="Contact")
        public String getContact() {
            return contact;
        }
    
        public void setContact(String contact) {
            this.contact = contact;
        }
    
    
        @Column(name="First_Name")
        public String getFirstName() {
            return firstName;
        }
    
        public void setFirstName(String firstName) {
            this.firstName = firstName;
        }
    
    
        @Column(name="Last_Name")
        public String getLastName() {
            return lastName;
        }
    
        public void setLastName(String lastName) {
            this.lastName = lastName;
        }
    
    
        @Column(name="Gender")
        public String getGender() {
            return gender;
        }
    
        public void setGender(String gender) {
            this.gender = gender;
        }
    
    
        @Column(name="Address")
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
    
        @Column(name="Age")
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
    
        @Column(name="Email")
        public String getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
    
    
        @Column(name="Count_Books")
        public String getCountBooks() {
            return countBooks;
        }
    
        public void setCountBooks(String countBooks) {
            this.countBooks = countBooks;
        }
    
        @ManyToMany(cascade=CascadeType.ALL)
        @JoinTable(name="User_Language", joinColumns = { 
                @JoinColumn(name = "User_Id", nullable = false, updatable = false) }, 
                inverseJoinColumns = { @JoinColumn(name = "Language_Id", 
                        nullable = false, updatable = false) })
        public Set<Language> getLanguages() {
            return languages;
        }
    
        public void setLanguages(Set<Language> languages) {
            this.languages = languages;
        }
    
        @ManyToMany
        @JoinTable(name="User_Favorite", joinColumns = { 
                @JoinColumn(name = "User_Id", nullable = false, updatable = false) }, 
                inverseJoinColumns = { @JoinColumn(name = "Book_Id", 
                        nullable = false, updatable = false) })
        public Set<Book> getFavorites() {
            return favorites;
        }
    
        public void setFavorites(Set<Book> favorites) {
            this.favorites = favorites;
        }   
    
    }
    

    UserSubscription:

    package com.model;
    
    import java.sql.Date;
    
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.OneToOne;
    
    @Entity
    public class UserSubscription {
    
        private int userSubscriptionId;
        private Subscription subscription;
        private User user;
        private Date subscriptionStartDate;
        private Date subscriptionEndDate;
        private int status;
    
    
        @Id
        @GeneratedValue
        @Column(name="User_Subscription_Id")
        public int getUserSubscriptionId() {
            return userSubscriptionId;
        }
        public void setUserSubscriptionId(int userSubscriptionId) {
            this.userSubscriptionId = userSubscriptionId;
        }
    
        @Column(name="Subscription_Id")
        public Subscription getSubscription() {
            return subscription;
        }
        public void setSubscription(Subscription subscription) {
            this.subscription = subscription;
        }
        @OneToOne(mappedBy="userId")
        public User getUser() {
            return user;
        }
        public void setUser(User user) {
            this.user = user;
        }
    
        @Column(name="Subscription_Start_Date")
        public Date getSubscriptionStartDate() {
            return subscriptionStartDate;
        }
        public void setSubscriptionStartDate(Date subscriptionStartDate) {
            this.subscriptionStartDate = subscriptionStartDate;
        }
    
        @Column(name="Subscription_End_Date")
        public Date getSubscriptionEndDate() {
            return subscriptionEndDate;
        }
        public void setSubscriptionEndDate(Date subscriptionEndDate) {
            this.subscriptionEndDate = subscriptionEndDate;
        }
    
        @Column(name="Status")
        public int getStatus() {
            return status;
        }
        public void setStatus(int status) {
            this.status = status;
        }
    
    
    
    
    
    }
    

    Subscription:

    package com.model;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    
    @Entity
    public class Subscription {
    
    
        private int subscriptionId;
        private String name;
        private int period;
        private float fees;
        private int noOfBooks;
        private int Status;
    
        @Id
        @GeneratedValue
        public int getSubscriptionId() {
            return subscriptionId;
        }
        public void setSubscriptionId(int subscriptionId) {
            this.subscriptionId = subscriptionId;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getPeriod() {
            return period;
        }
        public void setPeriod(int period) {
            this.period = period;
        }
        public float getFees() {
            return fees;
        }
        public void setFees(float fees) {
            this.fees = fees;
        }
        public int getNoOfBooks() {
            return noOfBooks;
        }
        public void setNoOfBooks(int noOfBooks) {
            this.noOfBooks = noOfBooks;
        }
        public int getStatus() {
            return Status;
        }
        public void setStatus(int status) {
            Status = status;
        }
    
    
    
    }
    

    Exception while executing:

    Exception in thread "main" org.hibernate.AnnotationException: Referenced property not a (One|Many)ToOne: com.model.User.userId in mappedBy of com.model.UserSubscription.user
        at org.hibernate.cfg.OneToOneSecondPass.doSecondPass(OneToOneSecondPass.java:248)
        at org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1695)
        at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1424)
        at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1844)
        at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1928)
        at com.impetus.model.Check.main(Check.java:92)