Hibernate 注解实体关系(异常的org.hibernate.LazyInitializationException: could not initialize proxy )

53 篇文章 0 订阅
33 篇文章 0 订阅

实体关系
一.七种实体关系
(1)一对一(单向/双向) @OneToOne
(2)一对多(单向/双向) @OneToMany
(3)多对一(单向/双向)@ManyToOne
(4)多对多(双向)@ManyToMany

二.实体一对多双向自身关联关系
例子:Windows文件夹

作用:可以表示一种层次关系
实体:
package com.lyh.model;
import javax.persistence.*;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
@Entity
public class Folder implements Serializable {
     private int id;
     private String name;
     private Folder parentFolder;
     private Collection<Folder> childFolders =new ArrayList<Folder>();
     public Folder() {
     }
     public Folder(String name, Folder parentFolder, Collection<Folder> childFolders) {
         this.name = name;
         this.parentFolder = parentFolder;
         this.childFolders = childFolders;
     }
     @Id
     @GeneratedValue
     public int getId() {
         return id;
     }
     public void setId(int id) {
         this.id = id;
     }
     public String getName() {
         return name;
     }
     public void setName(String name) {
         this.name = name;
     }
    @ManyToOne
     public Folder getParentFolder() {
         return parentFolder;
     }
     public void setParentFolder(Folder parentFolder) {
         this.parentFolder = parentFolder;
     }
    @OneToMany(cascade={CascadeType.ALL},mappedBy = "parentFolder" /*,fetch=FetchType.EAGER*/)
     public Collection<Folder> getChildFolders() {
         return childFolders;
     }
     public void setChildFolders(Collection<Folder> childFolders) {
         this.childFolders = childFolders;
     }
}
实体关系图:

用到的注释说明:
@OneToMany
target Entity
targetEntity 属性是 Class 类型的属性。定义实体一对多关系中处于从属地位的实体类的类型。
mappedBy
mappedBy 属性是 String 类型的属性。mappedBy 属性的值是当前实体在关联实体中的属性名称,使用 mappedBy 可以定义实体类之间的双向关系。如果类之间是单向关系,不需要提供定义,如果类和类之间形成双向关系,我们就需要使用这个属性进行定义,否则可能引起数据 一致性的问题。
Cascade
cascade 属性的类型是 CascadeType[] 类型。cascade 属性定义实体和实体之间的级联关系。使用 cascade 属性定义的级联关系将被容器视为对当前类对象及其关联类对象采取相同的操作,而且这种关系是递归调用的。
cascade 的值只能从 CascadeType.PERSIST(级联新建)、CascadeType.REMOVE(级联删除)、CascadeType.REFRESH(级 联刷新)、CascadeType.MERGE(级联更新)中选择一个或多个。还有一个更方便的选择是使用 CascadeType.ALL,表示选择上面全部四项.cascade=ALL等价于cascade={PERSIST, MERGE, REMOVE, REFRESH}.。
fetch
fetch 属性是 FetchType 类型的属性。可选择项包括:FetchType.EAGER 和 FetchType.LAZY。前者表示关联关系的从类在主类加载的时候同时加载,后者表示关联关系的从类在自己被访问时才加载。默认值是 FetchType.EAGER。

@OneToMany默认类型为FetchType.LAZY
Optional
optional 属性是 boolean 类型的属性。optional 属性用于定义关联关系的从类对象是否必须存在。如果设置为 false,那么该属性就不能设置为 null。默认值是 true。
表结构:
会话Bean
package com.lyh.business;
import com.lyh.model.Folder;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
/**
* User: yhliu
* Date: 2007-9-15
* Time: 13:54:10
* Folder实体操作无状态会话Bean
*/
@Stateless
@Remote
public class FolderServiceBean implements FolderService {
     @PersistenceContext(unitName = "mysql")
     private EntityManager manager;
     public int createFolder(Folder folder) {
         manager.persist(folder);
         return folder.getId();
     }
     //根据文件夹名查找文件夹
     public Folder findFolder(String name) {
         Folder folder = null;
         try {
             Query query = manager.createQuery(
                     "from Folder f where f.name=?1");
             query.setParameter(1, name);
             folder = (Folder) query.getSingleResult();
         } catch (EntityNotFoundException notFound) {
             System.out.println("EntityNotFoundException");
         } catch (NonUniqueResultException nonUnique) {
             System.out.println("NonUniqueResultException");
         }
         return folder;
     }
     //根据文件夹名查找它下面的子文件夹
     public List<Folder> getChildFoldersByName(Folder folder) {
         List<Folder> childFolders = new ArrayList<Folder>();
         try {
             Query query = manager.createQuery(
                     "from Folder f where f.parentFolder=?1");
             query.setParameter(1, folder);
             childFolders = query.getResultList();
         } catch (EntityNotFoundException notFound) {
             System.out.println("EntityNotFoundException");
         }
         return childFolders;
     }
     //根据id查找文件夹
     public Folder findFolder(int id) {
         return manager.find(Folder.class, id);
     }
     //根据移除文件夹
     public void removeFolder(int id) {
         Folder parentfolder = manager.find(Folder.class, id);
         manager.remove(parentfolder);
     }
}
Client类
package com.lyh.clients;
import com.lyh.business.FolderService;
import com.lyh.model.Folder;
import javax.naming.Context;
import javax.rmi.PortableRemoteObject;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Created by IntelliJ IDEA.
* User: yhliu
* Date: 2007-9-15
* Time: 14:14:50
*/
public class Client {
     public static void main(String[] args) throws Exception {
         Context jndiContext = getInitialContext();
         Object ref = jndiContext.lookup("FolderServiceBean/remote");
         FolderService service = (FolderService)
                 PortableRemoteObject.narrow(ref, FolderService.class);
         //一级
         Folder rootFolder = new Folder("root", null, new ArrayList<Folder>());
         //二级
         Folder windowsFolder = new Folder("windows", null, new ArrayList<Folder>());
         Folder programFilesFolder = new Folder("programFiles", null, new ArrayList<Folder>());
         //三级
         Folder helpFolder = new Folder("help", null, new ArrayList<Folder>());
         Folder frontsFolder = new Folder("fronts", null, new ArrayList<Folder>());
         Folder winrarFolder = new Folder("winrar", null, new ArrayList<Folder>());
         //建立根文件夹和windows文件夹之间的联系
         rootFolder.getChildFolders().add(windowsFolder);
         windowsFolder.setParentFolder(rootFolder);
         //建立根文件夹和Programs Files文件夹之间的联系
         rootFolder.getChildFolders().add(programFilesFolder);
         programFilesFolder.setParentFolder(rootFolder);
         windowsFolder.getChildFolders().add(helpFolder);
         helpFolder.setParentFolder(windowsFolder);
         windowsFolder.getChildFolders().add(frontsFolder);
         frontsFolder.setParentFolder(windowsFolder);
         programFilesFolder.getChildFolders().add(winrarFolder);
         winrarFolder.setParentFolder(programFilesFolder);
         service.createFolder(rootFolder);
         Folder windows=service.findFolder("windows");
         if(windows==null){
             System.out.println("没有找到这个文件夹");
         }else{
              Collection<Folder> windowsFolderChilders= windows.getChildFolders();
             System.out.println("Windows目录下的子目录有:");
           //   for (Folder windowsFolderChilder : windowsFolderChilders) {
               //   System.out.println(windowsFolderChilder.getName());
         //     }
          List<Folder> folders=service.getChildFoldersByName(windows);
             for (Folder folder : folders) {
                 System.out.println(folder.getName());
             }
         }
       //   service.removeFolder(windows.getId());
     }
     public static Context getInitialContext() throws javax.naming.NamingException {
         return new javax.naming.InitialContext();
     }
}
可能出现的异常:
Exception in thread "main" org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.lyh.model.Folder.childFolders, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)
原因:关联实体的fetch=FetchType.LAZY 把fetch设置为FetchType.EAGER,可这未免也太影响了效率,
http://forum.springsource.org/showthread.php?t=65169
http://jhyimu2005.javaeye.com/blog/516386
http://hi.baidu.com/vsandjava/blog/item/328f52fbb8d063156c22eb74.html




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值