bingo

The way to my programmer


在使用springboot-jpa时调用getOne(Long id)方法报错

org.hibernate.LazyInitializationException: could not initialize proxy [com.bingo.entity.Domain#1] - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:155) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:268) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:73) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]

解决办法:

spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true

原因:
在使用hibernate进行持久化时,有时需要动态的改变对象的加载,比如在编辑页面里面lazy=true,而在浏览页面lazy=false,这样可以在需要lazy的地方才进行控制。而配置文件中Lazy属性是全局控制的,如何处理呢?
  当元素或者元素的lazy属性为true时,load() or get() or
find()加载这些对象时,Hibernate不会马上产生任何select语句,只是产生一个Obj代理类实例,只有在session没有关闭的情况下运行Obj.getXxx()时才会执行select语句从数据库加载对象,如果没有运行任何Obj.getXxx()方法,而session已经关闭,Obj已成游离状态,此时再运行Obj.getXxx()方法,Hibernate就会抛出”Could
not initialize proxy - the owning Session was
closeed”的异常,是说Obj代理类实例无法被初始化。然而想在Session关闭之前不调用Obj.getXxx()方法而关闭Session之后又要用,此时只要在Session关闭之前调用Hibernate.initialize(Obj)或者Hibernate.initialize(Obj.getXxx())即可,net.sf.hibernate.Hibernate类的initialize()静态方法用于在Session范围内显示初始化代理类实例。
  在配置文件里面可以用lazy=true,在程序里面可以用强制加载的方法Hibernate.initialize(Object
proxy) 方法强制加载这样就相当于动态改变为lazy=false。
  但在使用时需要注意的一点是:其中的proxy是持久对象的关联对象属性,比如A实体,你要把A的关联实体B也检出,则要写Hibernate.initialize(a.b)。

注意:

使用hibernate.enable_lazy_load_no_trans配置时,需要注意:
这种情形下,每次初始化一个实体的关联就会创建一个临时的session来加载,每个临时的session都会获取一个临时的数据库连接,开启一个新的事物。这就导致对底层连接池压力很大,而且事物日志也会被每次flush.



springboot-jpa LazyInitializationException Eureka Server自我保护不关掉停掉的服务解决办法