美文网首页
浅谈Hibernate懒加载与org.hibernate.Laz

浅谈Hibernate懒加载与org.hibernate.Laz

作者: xdqkid | 来源:发表于2017-08-04 18:59 被阅读0次

    何为懒加载

    懒加载又称延迟加载,是当在真正需要数据的时候,才真正执行数据加载操作。也就是说,当使用到对象的具体属性时,才进行加载。

    举个例子来说,一本书(Books)有很多章节(Chapters),一般加载数据的时候,加载Books的同时会同时把Chapters加载上来,而懒加载就是加载Books的属性时不会将Books中的Chapters立刻加载上来,只有在使用到Chapters中的属性时,才将Chapters加载出来。

    @Entity
    @Table
    public class Books {
        private int id;
        private String name;
        private Set<Chapters> chapters = new HashSet<Chapters>();
        
        @Id
        @GeneratedValue(strategy=GenerationType.AUTO)
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        @Column
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        @OneToMany(targetEntity=Chapters.class,mappedBy="book")
        public Set<Chapters> getChapters() {
            return chapters;
        }
        public void setChapters(Set<Chapters> chapters) {
            this.chapters = chapters;
        }
        public Books() {
            super();
        }
        public Books(String name) {
            super();
            this.name = name;
        }
        
    }
    
    
    @Entity
    @Table
    public class Chapters {
        
        private int id;
        private int number;
        private Books book;
        
        @Id
        @GeneratedValue(strategy=GenerationType.AUTO)
        @Column
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        @Column
        public int getNumber() {
            return number;
        }
        public void setNumber(int number) {
            this.number = number;
        }
        @ManyToOne(targetEntity=Books.class)
        public Books getBook() {
            return book;
        }
        public void setBook(Books book) {
            this.book = book;
        }
        public Chapters() {
            super();
        }
        public Chapters(int number, Books book) {
            super();
            this.number = number;
            this.book = book;
        }
        
        
    }
    
    

    代理模式(Proxy Pattern)

    理解Hibernate懒加载之前,需要简单了解什么是代理模式。

    代理模式就是为其他对象提供一种代理以控制对这个对象的访问。以一段加载图片的代码为例。

    public interface Image {
        public void load();
    
    }
    

    创建一个背景图(Background)需要耗时2.333秒

    public class Background implements Image {
    
        public Background() {
            super();
            try {
                Thread.sleep(2333);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public void load() {
            System.out.println("加载图片中...");
        }
    }
    

    代理类如下

    public class ImageProxy implements Image {
        
        private Image image;
    
        public ImageProxy(Image image) {
            super();
            this.image = image;
        }
    
        @Override
        public void load() {
            if (null == image) {
                image = new Background();
            }
            image.load();
        }
        
    }
    
    public class Test {
    
        public static void main(String[] args) {
            long startTime = System.currentTimeMillis();
            Image imageProxy = new ImageProxy(null);
            long endTime = System.currentTimeMillis();
            System.out.println("生成代理耗时:" + (endTime - startTime));
            imageProxy.load();
            long endTime2 = System.currentTimeMillis();
            System.out.println("访问耗时:" + (endTime2 - startTime));
            
        }
    
    }
    /*
    生成代理耗时:0
    加载图片中...
    访问耗时:2335
    */
    

    Background的创建被推迟到使用时才创建,优点显而易见:

    • 提高了获取Background对象的系统性能。
    • 减少了对象在内存中存在的时间,节约了系统内存的开销。
    • 除此之外,倘若在Test程序中不调用imageProxy的load()方法,在这种情况下,使用代理模式就可以不创建Background对象,打打提高了系统的运行性能。

    这里仅谈与懒加载有关的部分代理模式内容,其他内容不再阐述。

    Hibernate懒加载与代理模式(Proxy Pattern)

    Hibernate懒加载所采用的设计模式便是代理模式,因此在很多情况下能节约很大的系统开销,上面已经说明,这里不再阐述。

    懒加载特性与org.hibernate.LazyInitializationException

    明白了Hibernate懒加载与代理模式后,对于org.hibernate.LazyInitializationException也就明白了。由于懒加载的特性,在Hibernate Session范围之外访问未初始化的集合或者代理都会抛出org.hibernate.LazyInitializationException。因此,在Session的范围之内访问的集合或代理即可解决该问题。

    这里博主给出三种解决方案,仅供参考。

    解决方案一: 不使用懒加载

    在配置文件或注解中,将懒加载设置为fetch=FetchType.EAGER或false。

    这种做法,可能会把不需要的数据也加载上来,影响应用性能。

    解决方案二: Open Session In View模式

    利用过滤器(Filter),在用户请求结束、页面生成结束时关闭Session,保证在视图显示层一直打开Session。

    这种做法也比较简单,似乎还不错,但是副作用却不容小视。在DAO层数据已经加载完毕后,数据库Connection在在用户请求结束、页面生成结束时才关闭。因而各种原因,如传输数据大、数据传输速率低等问题会导致数据库Connection长时间被占用不关闭,造成连接池不足、网页访问慢、网页假死等现象。

    解决方案三:手动初始化数据

    在关闭Session之前,初始化代理属性或者集合属性。如:

        for (Chapters chapter : book.getChapters());
    

    当然这样代码可读性较差,Hibernate也提供了一种方法

        Hibernate.initialize(book.getChapters());
    

    相关文章

      网友评论

          本文标题:浅谈Hibernate懒加载与org.hibernate.Laz

          本文链接:https://www.haomeiwen.com/subject/vgjblxtx.html