我使用的是hibernate 4.3,实体用的是注解进行配置:
我碰到很奇怪的问题,我没有让hibernate进行lazy的操作,并且不希望有这类的操作出现。我在网络上翻了一下,这类报错应该是懒加载造成的:session关闭了,配置了lazy的属性无法拿到其内容,实体中的代理类无法查询数据报错。可是我这里没有配置任何的懒加载操作啊,为什么还有这种报错?是不是hibernate给我的还是一个代理类呢?如何让他给我本身的实体,而不是代理类呢?这报错让我无法进行实体序列化成为json了。
实体类
@Entity @Lazy(false) public class Organization { @Id @Column(length=32) @GeneratedValue(generator="id") @GenericGenerator(name="id",strategy="uuid") private String id; //组织名称 @Column(nullable=false) private String name; //顺序 private Double showorder; //上级组织 @ManyToOne @JoinColumn(name="supOrg") private Organization supOrg; //组织类型 @Column(length=32) private String type; //下级组织 @OneToMany(mappedBy="supOrg") @Lazy(false) private Set<Organization> organizations=new HashSet<Organization>(); //下级人员 @OneToMany(mappedBy="org") private Set<UserInfo> userInfos=new HashSet<UserInfo>(); //包含岗位 @OneToMany(mappedBy="org") private Set<Station> stations=new HashSet<Station>();
..省略get,set
测试代码:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("/SpringContext.xml") public class TestOrganization { @Resource private OrganizationService organiationService; @Resource private SessionUtil sessionUtil; /*@Resource private SessionUtil sessionUtil;*/ @Test public void insertUserInfo(){ try { Session s=sessionUtil.getSession(); Query q=s.createQuery("from Organization where id=:id").setString("id", "402893814fbb4e88014fbb4e93680000"); Organization org=(Organization)q.uniqueResult(); //Hibernate.initialize(org.getOrganizations()); s.close(); System.out.println(org.getOrganizations()==null); System.out.println(org.getOrganizations().size()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
Hibernate:
/*
from
Organization
where
id=:id */ select
organizati0_.id as id1_2_,
organizati0_.name as name2_2_,
organizati0_.showorder as showorde3_2_,
organizati0_.supOrg as supOrg7_2_,
organizati0_.treecode as treecode4_2_,
organizati0_.treepath as treepath5_2_,
organizati0_.type as type6_2_
from
Organization organizati0_
where
organizati0_.id=?
Hibernate:
select
organizati0_.id as id1_2_0_,
organizati0_.name as name2_2_0_,
organizati0_.showorder as showorde3_2_0_,
organizati0_.supOrg as supOrg7_2_0_,
organizati0_.treecode as treecode4_2_0_,
organizati0_.treepath as treepath5_2_0_,
organizati0_.type as type6_2_0_
from
Organization organizati0_
where
organizati0_.id=?
false
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.elink.org.model.Organization.organizations, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:575)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:214)
at org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:155)
at org.hibernate.collection.internal.PersistentSet.size(PersistentSet.java:160)
at com.elink.org.test.TestOrganization.insertUserInfo(TestOrganization.java:37)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:73)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:73)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:224)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:83)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:68)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:163)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
fetch默认值:FetchType.EAGER。默认情况下,JPA持续性提供程序使用获取类型EAGER:这将要求持续性提供程序运行时必须迫切获取数据。如果这不适合于应用程序或特定的持久字段,请将fetch设置为FetchType.LAZY:这将提示持续性提供程序在首次访问数据(如果可以)时应不急于获取数据。已发现问题,结合的懒加载是自动的,一定要加入注解F etch=FetchType.EAGER才可以。
我又发现问题了,发现hibernate与json序列化相当不兼容。
首先@ahyyux22说的对,eager确实不能解决我的问题,治标不治本,多了很多冗余数据。
然后lazy的话,有问题无法解决,就是json序列化时,依旧会把所有数据查询出来,我试了fastjson和jackson都是这样,因为序列化时会询问那些manytoone和onetomany的属性,是否存在,导致hibernate进行这部分数据的查询,从而查询出了整个树的数据。查询网络上的办法,大部分是建议将这些数据配置忽略,这样的话,就等于废了使用Hibernate的意义了,不知道有没有大神能解决这个问题的?
我想了一下,应该是让hibernate查询出来的实体,脱离他的持久态,进入游离态,但是这样做因为其中有属性lazy,所以在json序列化时就会报错。有没有办法直接把hibernate查询出来的实体,脱离hibernate的代理?版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。