Hibernate 报错,could not initialize proxy - no Session

zhbsbccg 发布于 2015/10/17 16:11
阅读 2K+
收藏 0

我使用的是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)


加载中
0
__loong
__loong
fetch
默认值: FetchType.EAGER。
默认情况下,JPA 持续性提供程序使用获取类型 EAGER:这将要求持续性提供程序运行时必须迫切获取数据。
如果这不适合于应用程序或特定的持久字段,请将 fetch 设置为FetchType.LAZY:这将提示持续性提供程序在首次访问数据(如果可以)时应不急于获取数据。
0
zhbsbccg
zhbsbccg
已发现问题,结合的懒加载是自动的,一定要加入注解Fetch = FetchType.EAGER才可以。
0
zhbsbccg
zhbsbccg

引用来自“zhbsbccg”的评论

已发现问题,结合的懒加载是自动的,一定要加入注解Fetch = FetchType.EAGER才可以。
ok
0
ahyyxx222
ahyyxx222
改成FetchType.EAGER相当于放弃了LAZY的好处,不可取。应该是在需要这个数据的方法中通过Criteria参数或者hibernate.initialize操作取到你需要的LAZY数据。
0
zhbsbccg
zhbsbccg

我又发现问题了,发现hibernate与json序列化相当不兼容。

首先@ahyyux22 说的对,eager确实不能解决我的问题,治标不治本,多了很多冗余数据。

然后lazy的话,有问题无法解决,就是json序列化时,依旧会把所有数据查询出来,我试了fastjson和jackson都是这样,因为序列化时会询问那些manytoone和onetomany的属性,是否存在,导致hibernate进行这部分数据的查询,从而查询出了整个树的数据。查询网络上的办法,大部分是建议将这些数据配置忽略,这样的话,就等于废了使用Hibernate的意义了,不知道有没有大神能解决这个问题的?

zhbsbccg
zhbsbccg
我想了一下,应该是让hibernate 查询出来的实体,脱离他的持久态,进入游离态,但是这样做因为其中有属性lazy,所以在json序列化时就会报错。有没有办法直接把hibernate查询出来的实体,脱离hibernate的代理?
返回顶部
顶部