Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OnetoOne Bi-directional Association Error on using referenceColumnName

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.?

like image 421
Ankit Bansal Avatar asked Apr 21 '17 11:04

Ankit Bansal


2 Answers

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=?
like image 90
ryan2049 Avatar answered Oct 12 '22 10:10

ryan2049


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.

like image 41
Bhushan Uniyal Avatar answered Oct 12 '22 10:10

Bhushan Uniyal