Java JpaRepository.findOne();s对JpaRepository.getOne()的影响
我在下面的示例中使用spring引导、spring web和spring数据 我有一个名为Person的实体,我已经在数据库中填充了两个Java JpaRepository.findOne();s对JpaRepository.getOne()的影响,java,hibernate,jackson,spring-data,Java,Hibernate,Jackson,Spring Data,我在下面的示例中使用spring引导、spring web和spring数据 我有一个名为Person的实体,我已经在数据库中填充了两个Persons: 个人实体 @Entity public class Person { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(unique = true, nullable = false) private long id; private String name; p
Person
s:
个人实体
@Entity
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(unique = true, nullable = false)
private long id;
private String name;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Personne() {
}
public Personne(long id, String name) {
this.id = id;
this.name = name;
}}
@Repository
public interface PersonRepository extends JpaRepository<Person, Long> {
}
PersonRepository
@Entity
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(unique = true, nullable = false)
private long id;
private String name;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Personne() {
}
public Personne(long id, String name) {
this.id = id;
this.name = name;
}}
@Repository
public interface PersonRepository extends JpaRepository<Person, Long> {
}
用例1:
当我用personRepo.getOne(id)
替换personRepo.xxxx(id)
并点击localhost:8080/perss/1
I get无法写入JSON:org.hibernate.proxy.pojo.javassist.javassistlazInitializer类找不到序列化程序,也找不到创建BeanSerializer的属性(为了避免异常,请禁用SerializationFeature.FAIL\u ON \u EMPTY \u BEANS)
浏览器中出现错误,原因是getOne()方法将代理返回给jackson无法转换的人
用例2:
当我用personRepo.findOne(id)
替换personRepo.xxxx(id)
并点击localhost:8080/perss/1
时,我得到了正确JSON格式的所需Person对象(这个很好)
用例3:
当我将PersonController
getById()
方法的代码替换为以下代码时:
@RequestMapping(value = "/perss/{id}")
public Person getById(@PathVariable("id") long id) {
Person p1 = personRepo.findOne(id);
Person p2 = personRepo.getOne(id);
return p2;
}
然后点击localhost:8080/perss/1
I获得正确JSON格式的通缉犯对象
问题:
使用getOne()
给了我一个错误,但同时使用findOne()
和getOne()
给了我很好的结果
findOne()
如何影响getOne()
的行为
编辑
用例4
当我颠倒p1和p2的顺序时,我得到一个错误
@RequestMapping(value = "/perss/{id}")
public Person getById(@PathVariable("id") long id) {
Person p2 = personRepo.getOne(id);
Person p1 = personRepo.findOne(id);
return p2;
}
尝试返回
p1
,您可能会得到相同的错误
@RequestMapping(value = "/perss/{id}")
public Person getById(@PathVariable("id") long id) {
Person p1 = personRepo.findOne(id);
Person p2 = personRepo.getOne(id);
return p1;
}
你没有得到任何,因为你没有序列化p1
,它是JavassitLazInitializer
代理。你序列化了p2
,它已经很好了
这个也可以:
@RequestMapping(value = "/check/{id}")
public void getById(@PathVariable("id") long id) {
personRepo.getOne(id);
}
当对象从POJO转换为JSON时,会发生JSON序列化
序列化具有惰性init属性的bean时发生错误,因为序列化发生在其完全加载之前
您可以尝试使用findOne()
执行以下选项来修复错误:
应用程序.properties
文件(如异常消息所示):
spring.jackson.serialization.fail on empty bean=false
@JsonIgnoreProperties({“hibernateLazyInitializer”,“handler”})
它不会。而且对存储库的调用也不会调用JSON序列化过程。在同时使用
findOne()
和getOne()
时,调用顺序确实会影响结果,这是正确的
简短回答:这两种方法都将首先在持久性上下文中查找ID,并返回缓存值(如果存在)。如果在持久性上下文中找不到任何内容,它们将继续加载首选结果并缓存它。缓存值将在下一次运行时由另一个方法找到
- 如果
不在持久性上下文中,则id
将加载(并缓存)代理getOne(id)
- 如果
不在持久性上下文中,则id
将加载(并缓存)裸实体findOne(id)
findOne()
和getOne()
最终都调用了Hibernate的DefaultLoadEventListener.onLoad()
方法,但它们使用不同的loadType参数调用它:
最终委托给getOne()
,它指定SessionImpl.IdentifierLoadAccessImpl.doGetReference()
最终传递给LoadEventListener.LOAD的加载类型,LOAD
DefaultLoadEventListener.proxyOrLoad()
允许创建代理LoadEventListener.LOAD
最终委托给findOne()
,指定SessionImpl.IdentifierLoadAccessImpl.doLoad()
LoadEventListener.GET的loadType值,该值最终传递给
DefaultLoadEventListener.proxyOrLoad()
不允许创建代理LoadEventListener.GET
DefaultLoadEventListener.proxyOrLoad()
中设置断点,以验证传入的LoadType options
参数的allowProxyCreation
字段是否具有不同的值,具体取决于调用它的是findOne()
还是getOne()
您可以看到,如果allowProxyCreation
为true,并且没有代理,那么proxyOrLoad()
将返回CreateProxyIfEssential()
的结果。在使用仅getOne()
的情况下,这将导致返回代理
如果在getOne()
之前为相同的实体类型和ID调用了findOne()
,那么当getOne()
调用进入createProxyIfEssential()
时,它将提前返回,因为该实体已在持久性上下文中找到。在这种情况下,调用getOne()
不会导致创建代理
如果在findOne()
之前调用getOne()
,那么代理将被创建并存储在persiste中