我在学生
和地址
之间有一个一对一的关系。我希望 Student
的 firstName
和 lastName
字段被延迟加载。我还想为 address
字段添加惰性。
这些是我的实体类:
@Entity
@Table(name = "students")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToOne(mappedBy = "student", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@LazyToOne(LazyToOneOption.NO_PROXY)
private Address address;
@Basic(fetch = FetchType.LAZY)
@Column(name = "first_name")
private String firstName;
@Basic(fetch = FetchType.LAZY)
@Column(name = "last_name")
private String lastName;
// getters and setters
}
地址类:
@Entity
@Table(name = "addresses")
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToOne
@JoinColumn(name = "s_id")
private Student student;
@Column
private String street;
// getters and setters
}
我的测试方法如下所示(Java 8 lambda 只是在后面创建一个实体管理器并在事务中执行所有操作):
@Test
public void dummyTest() {
JPA_UTILS.runInTransaction(e -> {
Student s = e.find(Student.class, 150L);
System.out.println("----------++++++++++++++-----------");
s.getFirstName();
System.out.println("----------++++++++++++++-----------");
});
}
因此,我在这里从数据库加载现有学生,然后获取惰性属性 firstName
(映射到 first_name
列)。问题是 Hibernate 不仅加载 firstName
,还加载 lastName
和 address
字段:
just.hibernate.one2one.TestApp > dummyTest STANDARD_OUT
Hibernate:
select
student0_.id as id1_1_0_
from students student0_
where student0_.id=?
----------++++++++++++++-----------
Hibernate:
/* sequential select just.hibernate.one2one.Student */
select
student_.first_name as first_na2_1_,
student_.last_name as last_nam3_1_
from students student_
where student_.id=?
Hibernate:
/* load just.hibernate.one2one.Address */
select
address0_.id as id1_0_1_,
address0_.street as street2_0_1_,
address0_.s_id as s_id3_0_1_,
student1_.id as id1_1_0_
from addresses address0_
left outer join students student1_ on address0_.s_id=student1_.id
where address0_.s_id=?
----------++++++++++++++-----------
我不想要这种行为,我只想加载我请求的内容。有人可以帮我找出问题所在吗?
谢谢
更新1:
检测是用maven完成的,我只发布相关代码(我已经尝试过使用gradle并得到相同的结果)
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>process-classes</phase>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
<configuration>
<tasks>
<taskdef name="instrument" classname="org.hibernate.tool.instrument.javassist.InstrumentTask">
<classpath>
<path refid="maven.runtime.classpath" />
<path refid="maven.plugin.classpath" />
</classpath>
</taskdef>
<instrument verbose="false">
<fileset dir="${project.build.outputDirectory}">
<include name="**/*.class"></include>
</fileset>
</instrument>
</tasks>
</configuration>
</plugin>
最佳答案
有两个重要的资源可以正确理解这个问题。首先,属性的延迟加载不是标准设置。请参阅:
Hibernate supports the lazy fetching of individual properties. This optimization technique is also known as fetch groups. Please note that this is mostly a marketing feature; optimizing row reads is much more important than optimization of column reads. However, only loading some properties of a class could be useful in extreme cases.
其次,基于上述文档部分,有一篇详细的文章:
虽然这与 NHibernate 有关,但内容是相同的,因为该功能来自 Hibernate。
我们可以在那里阅读:
What about multiple lazy properties? NHibernate support them, but you need to keep one thing in mind. NHibernate will load all the entity’s lazy properties, not just the one that was immediately accessed. By that same token, you can’t eagerly load just some of an entity’s lazy properties from HQL.
同样,我们可以理解属性的lazy
设置不是标准设置。它适用于一些非常具体的情况,例如:
This feature is mostly meant for unique circumstances, such as Person.Image, Post.Text, etc. As usual, be cautious in over using it.
摘要:延迟加载属性(ValueTypes/字符串,而不是关联)适用于特殊情况。它应该帮助我们避免加载一些巨大的列。但是,一旦访问这样的属性,所有其他属性也会加载
关于hibernate - 当要求加载惰性字段时,Hibernate 会加载所有惰性字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25487148/