Friday, August 4, 2017

OnetoOne Bi-directional Association Error on using referenceColumnName

Leave a Comment

Company Entity

@Entity @Table(name="company")  public class Company implements Serializable {      private static final long serialVersionUID = 1L;      @Id     @GeneratedValue     private int id;      @Column(name="company_id")     private int cmpId;      @Column(name="company_name")     private String companyName;      @OneToOne(fetch=FetchType.LAZY, mappedBy="company")     private Employee employee;     } 

Employee Entity

@Entity @Table(name="employee") public class Employee implements Serializable {      private static final long serialVersionUID = 1L;      @Id     @GeneratedValue     private int id;      @Column(name="emp_id")     private int empId;      @Column(name="emp_name")     private String empName;      @OneToOne(fetch=FetchType.LAZY)     @JoinColumn(name="cmp_id", referencedColumnName="company_id")     private Company company;  } 

Company Service

@Service public class CompanyService {      @Autowired     private CompanyRepository companyRepo;      public Company fetchCompany(int cmpId){         System.out.println("11111111111111111");         return companyRepo.findByCmpId(cmpId);     } } 

Company Repo

public interface CompanyRepository extends JpaRepository<Company, Integer>{       @Query(value="select a from Company a join fetch a.employee where a.cmpId = ?1")     public Company findByCmpId(int cmpId); } 

API

@RequestMapping("/cmp/{cmpId}") public void findCmp(@PathVariable int cmpId){     Company cmp = cmpService.fetchCompany(cmpId);     System.out.println(cmp.getEmployee().getEmpName()); } 

Issue is when I am trying to execute my code, I am getting following error:

  Hibernate: select company0_.id as id1_1_0_, employee1_.id as id1_2_1_, company0_.company_id as company_2_1_0_, company0_.company_name as company_3_1_0_, employee1_.cmp_id as cmp_id4_2_1_, employee1_.emp_id as emp_id2_2_1_, employee1_.emp_name as emp_name3_2_1_ from company company0_ inner join employee employee1_ on company0_.id=employee1_.cmp_id where company0_.company_id=? 2017-04-21 17:22:11.386 ERROR 10766 --- [nio-8105-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.orm.jpa.JpaSystemException: Error accessing field [private int com.example.domain.Company.cmpId] by reflection for persistent property [com.example.domain.Company#cmpId] : 1; nested exception is org.hibernate.property.access.spi.PropertyAccessException: Error accessing field [private int com.example.domain.Company.cmpId] by reflection for persistent property [com.example.domain.Company#cmpId] : 1] with root cause  java.lang.IllegalArgumentException: Can not set int field com.example.domain.Company.cmpId to java.lang.Integer     at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167) ~[na:1.8.0_91]     at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171) ~[na:1.8.0_91]     at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58) ~[na:1.8.0_91]     at sun.reflect.UnsafeIntegerFieldAccessorImpl.getInt(UnsafeIntegerFieldAccessorImpl.java:56) ~[na:1.8.0_91]     at sun.reflect.UnsafeIntegerFieldAccessorImpl.get(UnsafeIntegerFieldAccessorImpl.java:36) ~[na:1.8.0_91]     at java.lang.reflect.Field.get(Field.java:393) ~[na:1.8.0_91] 

How to fix this? Also when I have removed referenceColumnName, then the error is removed but them it is joining with primary key of company class, which I dont want.?

3 Answers

Answers 1

Exception :

 IllegalArgumentException: Can not set int field com.example.domain.Company.cmpId to java.lang.Integer 

Please use Integerinstead of int in Company as we as in Employee entity if id field.

 @Id     @GeneratedValue     private Integer id; 

Also please provide getter and setter methods for fields in your entity.

Answers 2

**Can not set int field com.example.domain.Company.cmpId to java.lang.Integer**  Hibernate except foreign key of employee table cmp_id, should be primary key of company. But in your code cmpId is not primary key.          @Column(name="company_id")         private int cmpId;  Please make that primary and check once.   Edited:- 1.         @OneToOne(fetch=FetchType.LAZY, mappedBy="company")         private Employee employee; change to:-         @OneToOne(fetch=FetchType.LAZY, mappedBy="company",optional=false)         private Employee employee;  2.         @OneToOne(fetch=FetchType.LAZY)         @JoinColumn(name="cmp_id", referencedColumnName="company_id")         private Company company; change to:-         @OneToOne(fetch=FetchType.LAZY)         @JoinColumn(name="cmp_id")         private Company company; 

Answers 3

This looks a bit funky, but I believe it works the way you requested.

Company

@Entity @Table(name = "company") public class Company implements Serializable {      private static final long serialVersionUID = 1L;      @Id     @GeneratedValue     private Integer id;      @Column(name = "comp_id")     private Integer compId;      @Column(name = "company_name")     private String companyName;      @OneToOne     @JoinColumn(name="emp_id", referencedColumnName="emp_id")     private Employee employee;      @PostPersist     public void postPersist() {         if (id != null && compId == null) {             setCompId(new Integer(id));         }     }      public Integer getId() {         return id;     }      public void setId(Integer id) {         this.id = id;     }      public String getCompanyName() {         return companyName;     }      public void setCompanyName(String companyName) {         this.companyName = companyName;     }      public Employee getEmployee() {         return employee;     }      public void setEmployee(Employee employee) {         this.employee = employee;     }      public Integer getCompId() {         return compId;     }      public void setCompId(Integer compId) {         this.compId = compId;     } } 

CompanyRepository

public interface CompanyRepository extends JpaRepository<Company, Integer> {      @Query(value = "select a from Company a join fetch a.employee as emp where a.compId = ?1")     public Company findByCmpId(int cmpId); } 

CompanyService

@Service public class CompanyService {      @Autowired     private CompanyRepository companyRepo;      public Company fetchCompany(int cmpId) {         return companyRepo.findByCmpId(cmpId);     } } 

Employee

@Entity @Table(name = "employee") public class Employee implements Serializable {      private static final long serialVersionUID = 1L;      @Id     @GeneratedValue     private Integer id;      @Column(name = "emp_id")     private Integer empId;      @Column(name = "emp_name")     private String empName;      @OneToOne     @JoinColumn(name="comp_id", referencedColumnName="comp_id")     private Company company;      @PostPersist     public void postPersist() {         if (id != null && empId == null) {             setEmpId(new Integer(id));         }     }      public Integer getId() {         return id;     }      public void setId(Integer id) {         this.id = id;     }      public Integer getEmpId() {         return empId;     }      public void setEmpId(Integer empId) {         this.empId = empId;     }      public String getEmpName() {         return empName;     }      public void setEmpName(String empName) {         this.empName = empName;     }      public Company getCompany() {         return company;     }      public void setCompany(Company company) {         this.company = company;     } } 

EmployeeRepository

public interface EmployeeRepository extends JpaRepository<Employee, Integer>  {     @Query(value = "select a from Employee a join fetch a.company as comp where a.empId = ?1")     public Employee findByEmpId(int cmpId); } 

EmployeeService

@Service public class EmployeeService {      @Autowired     private EmployeeRepository employeeRepo;      public Employee fetchEmployee(int empId) {         return employeeRepo.findByEmpId(empId);     } } 

Unit Tests

@RunWith(SpringRunner.class) @SpringBootTest public class RnlApplicationTests {      @Autowired     CompanyService companyService;      @Autowired     EmployeeService employeeService;      @Autowired     CompanyRepository companyRepository;      @Autowired     EmployeeRepository employeeRepository;      @Before      public void setup() {         Employee employee = new Employee();         employee.setEmpName("Test Employee");          Company company = new Company();         company.setCompanyName("Test Company");         company = companyRepository.save(company);          employee.setCompany(company);         employee = employeeRepository.save(employee);          company.setEmployee(employee);         company = companyRepository.save(company);          Employee employee2 = new Employee();         employee2.setEmpName("Test Employee2");          Company company2 = new Company();         company2.setCompanyName("Test Company2");         company2 = companyRepository.save(company2);          employee2.setCompany(company2);         employee2 = employeeRepository.save(employee2);          company2.setEmployee(employee2);         company2 = companyRepository.save(company2);     }      @Test     public void testRepository() {         Company company = companyService.fetchCompany(1);         assertThat(company).isNotNull();          Company company2 = companyService.fetchCompany(2);         assertThat(company2).isNotNull();          Employee employee = employeeService.fetchEmployee(1);         assertThat(employee).isNotNull();          Employee employee2 = employeeService.fetchEmployee(2);         assertThat(employee2).isNotNull();     } } 

The setup for the test is a bit repetitive, but I had to set it up that way to get these test cases working. You can probably figure out a better way.

Hibernate SQL output from Company test

select     company0_.id as id1_0_2_,     company0_.comp_id as comp_id2_0_2_,     company0_.company_name as company_3_0_2_,     company0_.emp_id as emp_id4_0_2_,     employee1_.id as id1_1_0_,     employee1_.comp_id as comp_id4_1_0_,     employee1_.emp_id as emp_id2_1_0_,     employee1_.emp_name as emp_name3_1_0_,     company2_.id as id1_0_1_,     company2_.comp_id as comp_id2_0_1_,     company2_.company_name as company_3_0_1_,     company2_.emp_id as emp_id4_0_1_  from     company company0_  left outer join     employee employee1_          on company0_.emp_id=employee1_.emp_id  left outer join     company company2_          on employee1_.comp_id=company2_.comp_id  where     company0_.comp_id=? 

Hibernate SQL output from Employee test

select     employee0_.id as id1_1_0_,     company1_.id as id1_0_1_,     employee0_.comp_id as comp_id4_1_0_,     employee0_.emp_id as emp_id2_1_0_,     employee0_.emp_name as emp_name3_1_0_,     company1_.comp_id as comp_id2_0_1_,     company1_.company_name as company_3_0_1_,     company1_.emp_id as emp_id4_0_1_  from     employee employee0_  inner join     company company1_          on employee0_.comp_id=company1_.comp_id  where     employee0_.emp_id=? 
If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment