1 Reply Latest reply: Sep 3, 2012 4:50 PM by 694537 RSS

    How to do JPA OneToOne relationship insert only one side of the relation

    694537
      Hi folks.

      In this moment I'm having a problem with my JPA implementation. I have two Entities as following:

      Entity Position
      package com.test;
      
      import java.io.Serializable;
      
      import javax.persistence.Column;
      import javax.persistence.Entity;
      import javax.persistence.Id;
      
      @Entity(name = "tbl_positions")
      public class Position implements Serializable {
              private static final long serialVersionUID = 1L;
      
              @Id
              @Column(name = "posid")
              private long id;
      
              @Column(name = "posname")
              private String name;
      
              public long getId() {
                      return id;
              }
      
              public void setId(long id) {
                      this.id = id;
              }
      
              public String getName() {
                      return name;
              }
      
              public void setName(String name) {
                      this.name = name;
              }
      
      }
      Entity Employee
      package com.test;
      
      import java.io.Serializable;
      
      import javax.persistence.Column;
      import javax.persistence.Entity;
      import javax.persistence.Id;
      import javax.persistence.JoinColumn;
      import javax.persistence.OneToOne;
      
      
      @Entity(name = "tbl_employee")
      public class Employee implements Serializable {
              private static final long serialVersionUID = 1L;
      
              @Id
              @Column(name = "empid")
              private long id;
      
              @Column(name = "empname")
              private String name;
      
              @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
              @JoinColumn(name = "emppositionid")
              private Position position;
      
      
              public long getId() {
                      return id;
              }
      
              public void setId(long id) {
                      this.id = id;
              }
      
              public String getName() {
                      return name;
              }
      
              public void setName(String name) {
                      this.name = name;
              }
      
             public Position getPosition() {
                      return position;
              }
      
              public void setPosition(Position position) {
                      this.position = position;
              }
      
      }
      In the other hand I have this Session Bean:

      Remote Interface
      package com.test;
      
      import javax.ejb.Remote;
      
      @Remote
      public interface EmployeeServiceRemote {
              public void createEmployee(Employee employee);
      }
      Remote Interface Implementation
      package com.test;
      
      import javax.ejb.Stateless;
      import javax.persistence.EntityManager;
      import javax.persistence.PersistenceContext;
      
      @Stateless
      public class EmployeeServiceImpl implements EmployeeServiceRemote {
      
              @PersistenceContext(unitName = "MyPersistenceUnit")
              private EntityManager entityManager;
      
              public EmployeeServiceImpl() {
              }
      
              public void createEmployee(Employee employee) {
                     Sequence sequence = new Sequence(this.entityManager);
                     long nextValue = sequence.getNextValue(SequenceName.EMPLOYEES);
                     employee.setId(nextValue);
                     this.entityManager.persist(employee);
              }
      
      }
      The previous code includes the class Sequence. By the moment it only generates a secuential value for using as primary key for the entity Employee.

      This is the content of the file persistence.xml
      <?xml version="1.0" encoding="UTF-8"?>
      <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
           <persistence-unit name="MyPersistenceUnit">
               <jta-data-source>java:/TESTDS</jta-data-source>
               <class>com.test.PositionEntity</class>
               <class>com.test.Employee</class>
               <properties>
                  <property name="hibernate.show_sql" value="true"/>
                  <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
              </properties>
          </persistence-unit>
      </persistence>
      This is my test class:
      package com.test;
      
      import javax.naming.Context;
      
      import org.junit.Before;
      import org.junit.Test;
      
      public class EmployeeTest {
      
           private static Employee getNewEmployee() {
                Position position = new Position();
                position.setId(1);
                position.setName("ENGINEER");
                
                Employee employee = new Employee();
      
                employee.setName("Jhon Doe");
                employee.setPosition(position);
                
                return employee;
           }
           
           private static EmployeeServiceRemote lookUpService() throws Exception {
                EmployeeServiceRemote service = null;
                //Do lookup ...
                return service;
           }
           
           @Test
           public void testCreateEmployee() throws Exception {
                Employee employee = getNewEmployee();
                EmployeeServiceRemote service = lookUpService();
                service.createEmployee(employee);
                System.out.println("Finish !");
           }
      
      }
      And finally, this is the database script:
      create table tbl_positions (
           posid numeric(10) not null,
           posname varchar(255) not null,
           primary key(posid)
      );
      
      create table tbl_employee (
           empid numeric(10) not null,
           empname varchar(255) not null,
           emppositionid numeric(10) not null,
           primary key(empid)
      );
      
      alter table tbl_employee add constraint fk_emp_pos foreign key (emppositionid) 
      references tbl_positions (posid);
      Before I executed test class EmployeeTest, I inserted one row in the table tbl_positions like this:
      insert into tbl_positions (posid, posname) values (1, 'ENGINEER');
      Because tbl_positions is a catalog and it most not be created when I create an Employee.

      My problem arise when I executed the test class EmployeeTest. When I invoke the method service.createEmployee(employee)+, I get the exception: Duplicate entry '1' for key 'PRIMARY'+ referencing the table tbl_positions+. This is a problem for me because what I need is that if a Position already exists, it only creates the Employee. Even better, for business constraints when I create an Employee, all the Positions must exist.

      Thanks for any help about it !!

      Best tegards,
      RADE