Jonas Jonas - 2 months ago 11
Java Question

OneToOne between two tables with shared primary key

I'm trying to set up the following tables using JPA/Hibernate:

User:

userid - PK
name

Validation:

userid - PK, FK(user)
code


There may be many users and every user may have max one validation code or none.

Here's my classes:

public class User
{
@Id
@Column(name = "userid")
@GeneratedValue(strategy = GenerationType.IDENTITY)
protected Long userId;

@Column(name = "name", length = 50, unique = true, nullable = false)
protected String name;

...
}

public class Validation
{
@Id
@Column(name = "userid")
protected Long userId;

@OneToOne(cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn(name = "userid", referencedColumnName = "userid")
protected User user;

@Column(name = "code", length = 10, unique = true, nullable = false)
protected String code;

...

public void setUser(User user)
{
this.user = user;
this.userId = user.getUserId();
}

...
}


I create a user and then try to add a validation code using the following code:

public void addValidationCode(Long userId)
{
EntityManager em = createEntityManager();
EntityTransaction tx = em.getTransaction();

try
{
tx.begin();

// Fetch the user
User user = retrieveUserByID(userId);

Validation validation = new Validation();
validation.setUser(user);
em.persist(validation);
tx.commit();
}
...
}


When I try to run it I get a org.hibernate.PersistentObjectException: detached entity passed to persist: User

I have also tried to use the following code in my Validation class:

public void setUserId(Long userId)
{
this.userId = userId;
}


and when I create a validation code I simply do:

Validation validation = new Validation();
validation.setUserId(userId);
em.persist(validation);
tx.commit();


But then since User is null I get org.hibernate.PropertyValueException: not-null property references a null or transient value: User.code

Would appreciate any help regarding how to best solve this issue!

Ben Ben
Answer

If you use Hibernate you can also use

public class Validation {        
       private Long validationId;
       private User user;

        @Id
        @GeneratedValue(generator="SharedPrimaryKeyGenerator")
        @GenericGenerator(name="SharedPrimaryKeyGenerator",strategy="foreign",parameters =  @Parameter(name="property", value="user"))
        @Column(name = "VALIDATION_ID", unique = true, nullable = false)
        public Long getValidationId(){
              return validationId;
        }

        @OneToOne
    @PrimaryKeyJoinColumn
    public User getUser() {
    return user;
    }

Hibernate will make sure that the ID of Validation will be the same as the ID of the User entity set.

Comments