Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/jenkins/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JpaRepository.findOne();s对JpaRepository.getOne()的影响_Java_Hibernate_Jackson_Spring Data - Fatal编程技术网

Java JpaRepository.findOne();s对JpaRepository.getOne()的影响

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

我在下面的示例中使用spring引导、spring web和spring数据

我有一个名为Person的实体,我已经在数据库中填充了两个
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

  • 使用惰性init属性注释实体,如:

    @JsonIgnoreProperties({“hibernateLazyInitializer”,“handler”})

  • 因此,回答这个问题:

    findOne()如何影响getOne()的行为


    它不会。而且对存储库的调用也不会调用JSON序列化过程。

    在同时使用
    findOne()
    getOne()
    时,调用顺序确实会影响结果,这是正确的

    简短回答:这两种方法都将首先在持久性上下文中查找ID,并返回缓存值(如果存在)。如果在持久性上下文中找不到任何内容,它们将继续加载首选结果并缓存它。缓存值将在下一次运行时由另一个方法找到

    • 如果
      id
      不在持久性上下文中,则
      getOne(id)
      将加载(并缓存)代理
    • 如果
      id
      不在持久性上下文中,则
      findOne(id)
      将加载(并缓存)裸实体
    详细回答:我遇到了同样的问题,我的项目使用了Hibernate 5.2.4.Final。发生的细节涉及一些Hibernate代码。调试了一段时间后,我发现
    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中