我正在使用JPA 2.0与EclipseLink持久性提供程序和Hibernate实体管理器4.3.10.Final。我在Employee和Office实体之间有@ManyToOne关系。我正在使用EntityManagerFactory插入一个新的Employee。员工实例引用现有的Office。代码有效但查询显示它正在获取Office的所有列而不仅仅是officeId。如何微调查询以避免在插入新员工时获取Office的所有列?我尝试在@ManyToOne上使用FetchType.LAZY,但它不起作用。
Employee.java
@Entity
public class Employee {
@Id
@SequenceGenerator(name="employeeSequence",allocationSize=1, sequenceName="EMP_SEQ")
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="employeeSequence")
private int empId;
@Column(name="FIRST_NAME")
private String firstName;
@Column(name="LAST_NAME")
private String lastName;
@Column(name="DOB")
private Date dateOfBirth;
private Date hireDate;
@ManyToOne
@JoinColumn(name="location")
private int location;
Office.java
@Entity
public class Office {
@Id
private int officeId;
private String location;
private String address1;
private String address2;
private String city;
private String state;
private String country;
private String zipcode;
创建Employee对象的代码
Employee emp = new Employee();
emp.setFirstName(firstName);
emp.setLastName(lastName);
emp.setDateOfBirth(dob);
emp.setHireDate(hiredate);
Office office = new Office();
office.setOfficeId(officeId);
emp.setLocation(office);
SQL查询
Hibernate:
select
EMP_SEQ.nextval
from
dual
Hibernate:
select
office_.officeId,
office_.address1 as address2_1_,
office_.address2 as address3_1_,
office_.city as city4_1_,
office_.country as country5_1_,
office_.location as location6_1_,
office_.state as state7_1_,
office_.zipcode as zipcode8_1_
from
Office office_
where
office_.officeId=?
Hibernate:
insert
into
Emp
(DOB, FIRST_NAME, hireDate, LAST_NAME, location, empId)
values (?, ?, ?, ?, ?, ?)
答案 0 :(得分:0)
开发人员在保存新对象时,基于某些外键值查询数据库以获取关系的持久实例是很常见的,如下所示:
@Entity
public class Employee {
// other stuff removed for breavity
@ManyToOne
private Office office;
}
@Entity
public class Office {
// no relationship back to Employee
}
// some repository method
public Employee save(String employeeName, Long officeId) {
final Office office = entityManager.find( Office.class, offceId );
final Employee employee = new Employee( employeeName, officeId );
entityManager.persist( employee );
return employee;
}
在这种情况下,持久性提供程序将查询数据库以构造Office
实体,以便在持久化时将标识符与Employee
相关联。正如您所注意到的,这不仅是不必要的,而且会影响性能。
避免数据库提取的另一个解决方案是在本机Hibernate API方面使用Session#load
或在JPA方面使用EntityManager#getReference
。对于所有意图和目的,它们是同义词,因为它们接受类类型和主键值,并构造代表类型类型的代理,如果访问它的内部状态将被懒惰地加载。
所以通过将上面的存储库方法更改为:
// some repository method
public Employee save(String employeeName, Long officeId) {
final Office office = entityManager.getReference( Office.class, offceId );
final Employee employee = new Employee( employeeName, officeId );
entityManager.persist( employee );
return employee;
}
不应再对Office
的数据存储进行提取。