我一直在玩JPA,遇到过这个场景,想知道如何解决这个问题。
我有2个表,即公司和员工。 因此,员工只能在一家公司工作,因此@OneToOne单向映射在Employee类中完成。公司表中的公司详细信息已经存在。
因此,当我尝试将记录插入Employee表时,我甚至创建了对该公司的引用,将其添加到Employee类并使用我的EmployeeRepository的保存方法保存它。由于company_id已经存在于Company表中,因此它应该仅引用它而不是创建新公司。但这不会发生。
我得到一个例外company object is still in the transient state.
我可以通过添加CascadeType.All
来解决这个问题,但我不需要插入公司,而是必须将公司与员工联系起来。
以下是代码段。
员工类
@Entity
@Table(name = "employee")
@Setter
@Getter
public class Employee
{
@Id
@GeneratedValue
private Long id;
@Column(name = "employee_id")
private Integer employeeId;
@Column(name = "employee_name")
private String employee_name;
@OneToOne
@JoinColumn(name = "company_id")
private Company company;
}
公司类
@Entity
@Table(name = "company")
@Setter
@Getter
public class Company
{
@Id
@GeneratedValue
@Column(name = "company_id")
private Long id;
@Column(name = "company_name")
private String companyName;
}
公司表
company_id company_name
1 Dell
2 Apple
3 Microsoft
以下是我创建Employee对象的方法
Employee emp = new Employee();
emp.setEmployeeId(10);
emp.setEmployeeName("Michael");
Company company = new Company();
company.setId(1);
emp.setCompany(company);
employeeRepository.save(emp);
请有人告诉我如何将公司课程与员工班级联系起来,而不是再节省一家公司。
答案 0 :(得分:1)
对我而言,最好的解决方案是用代理将您的公司延迟加载。要使用Spring Data JPA做到这一点,您需要使公司存储库扩展为JpaRepository
。这使您可以访问方法getOne:
Employee emp = new Employee();
emp.setEmployeeId(10);
emp.setEmployeeName("Michael");
emp.setCompany(companyRepository.getOne(1))
employeeRepository.save(emp);
如果没有提供给定ID的公司,则会抛出EntityNotFoundException
。
使用代理,大多数情况下避免了对数据库的请求,因为Hibernate使用其缓存来检查公司的存在。但是如果我的记忆正确地为我服务,那么Hibernate将在每次调用代理的getter时向数据库发出一个请求,除了getId()
之外。因此,对于您而言,这是一个很好的解决方案,但请不要一直使用它。
答案 1 :(得分:0)
假设Company
可能有多个Employee
,则关系为ManyToOne
,而不是OneToOne
。
如果要引用现有实体,请加载它而不是创建新实体:
Employee emp = new Employee();
// ...
emp.setCompany(companyRepository.findById(1));
employeeRepository.save(emp);