Hibernate框架进阶(三)

Hibernate事务

hibernate使用事务来对数据的增删改查实现统一的操作,在事务中的多个操作行为,要么都成功,要么都失败

代码实现如下

由Session.beginTransaction()方法开始,Session.getTransaction..commit()结束

        SessionFactory sf = new Configuration().configure().buildSessionFactory();
 
        Session s = sf.openSession();
        s.beginTransaction();
 
        Product p = (Product) s.get(Product.class, 0);
        s.delete(p);
 
        Product p2 = (Product) s.get(Product.class, 1);
        p2.setName("长度超过30的字符串作为产品名称长度超过30的字符串作为产品名称长度超过30的字符串作为产品名称长度超过30的字符串作为产品名称");
        s.update(p2);
 
        s.getTransaction().commit();
        s.close();
        sf.close();

本例子执行了两个操作

第一个删除id=0的产品,这个会成功,但由于第二个操作产品名称超过了数据库设置的长度,所以两个都没有生效

Hibernate延迟加载

hibernate的延迟加载分为属性延迟加载和关系延迟加载

属性延迟加载

当使用load()方法来获取对象的时候,只有访问了这个对象的属性,hibernate才会到数据库进行查询,否则不会访问数据库

代码实现如下

        Product p = (Product)s.load(Product.class, 0);
        System.out.println("log1");
        System.out.println(p.getName());
        System.out.println("log2");

关系延迟加载

关系延迟加载就是在关系映射章节中映射文件中 涉及到的lazy属性

<set name="products" lazy="false"> 

它主要体现在当获取对象的时候不会去加载有关系映射的对象的信息,只有当获取关系映射对象属性的时候才会对其进行加载

Hibernate级联

级联用本例来解释就是在没有配置级联的时候删除分类,对应的产品不会被删除,否则反之

级联有四种类型:

all:所有操作都执行级联操作

none:所以操作都不执行级联操作,默认值

delete:删除时执行级联操作

save-update:保存和更新时执行级联操作

配置级联只需要在其配置文件对应属性上添加cascade属性

        <set name="products" cascade="delete" lazy="false">
            <key column="cid" not-null="false" />
            <one-to-many class="Product" />
        </set>

Hibernate缓存

Hibernate缓存有一级缓存和二级缓存,一级缓存存放在Session中,默认开启,二级缓存存放在SessionFactory,默认关闭。所以这里只讲二级缓存

二级缓存

先来看没有配置二级缓存的情况

        SessionFactory sf = new Configuration().configure().buildSessionFactory();
 
        Session s = sf.openSession();
        s.beginTransaction();
        Category p1 = (Category) s.get(Category.class, 1);
        Category p2 = (Category) s.get(Category.class, 1);
        s.getTransaction().commit();
        s.close();
        Session s2 = sf.openSession();
        s2.beginTransaction();
        Category p3 = (Category) s2.get(Category.class, 1);
 
        s2.getTransaction().commit();
        s2.close();
        sf.close();

这里创建了两个Session,第一个Session里,由于有一级缓存,所以只会执行一条SQL语句,但在第二个Session里,因为没有配置二级缓存,即使获取同一个对象,也需要重新执行了一条相同的SQL语句

如何配置二级缓存?

在pom.xml中添加hibernate-ehcache缓存库依赖

		<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-ehcache -->
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-ehcache</artifactId>
			<version>5.3.1.Final</version>
		</dependency>

在hibernate.cfg.xml中增加对二级缓存的配置

		<!-- 启用二级缓存 -->
		<property name="hibernate.cache.use_second_level_cache">true</property>
		<!-- 设置二级缓存插件EHCache的Provider类 -->
		<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
		<!-- 类的二级缓存配置 -->
		<class-cache usage="read-only" class="pojo.Category" />

在src/main/java下创建配置文件ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
    <!-- 设置缓存数据文件的存储目录 -->
	<diskStore path="java.io.tmpdir" />
	<!-- 设置缓存的默认数据过期策略 -->
	<defaultCache maxElementsInMemory="1000" eternal="false"
		timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" />
		
	<!-- 设置具体的命名缓存的数据过期策略 -->
	<cache name="pojo.Category" maxElementsInMemory="500" eternal="true"
		timeToIdleSeconds="0" timeToLiveSeconds="0" overflowToDisk="false" />

</ehcache>  

在上述配置中,diskStore元素设置缓存数据文件的存储目录;defaultCache元素设置缓存的默认数据过期策略;cache元素设置具体的命名缓存的数据过期策略。每个命名缓存代表一个缓存区域,命名缓存机制允许用户在每个类以及类的每个集合的粒度上设置数据过期策略;
在defaultCache元素中,maxElementsInMemory属性设置缓存对象的最大数目;eternal属性指定是否永不过期,true为不过期,false为过期;timeToldleSeconds属性设置对象处于空闲状态的最大秒数;timeToLiveSeconds属性设置对象处于缓存状态的最大秒数;overflowToDisk属性设置内存溢出时是否将溢出对象写入硬盘;

到这里二级缓存就已配置完成,此时再对章节开始代码进行测试,在第二个Session中不会再执行SQL语句了,而是从二级缓存SessionFactory中取出。

Hibernate分页查询

Hibernate使用Criteria进行分页查询,步骤如下:

1.首先使用Session.createCriterria()方法构建出一个Criteria

2.使用Criteria.add()方法添加条件限制

3.Criteria.setFirstResult()方法表示从第几条数据开始

4.Criteria.setMaxResult()方法表示一共查询几条数据

代码如下:

        String name = "iphone";
          
        Criteria c= session.createCriteria(Product.class);
        c.add(Restrictions.like("name", "%"+name+"%"));
        c.setFirstResult(2);
        c.setMaxResults(5);
         
        List<Product> ps = c.list();
        for (Product p : ps) {
            System.out.println(p.getName());
             
        }

Hibernate使用C3P0连接池

C3P0是免费的第三方数据库连接池,在数据库连接方面有着很不错的表现

在pom.xml中添加C3P0连接池依赖

		<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-c3p0 -->
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-c3p0</artifactId>
			<version>5.3.1.Final</version>
		</dependency>

在hibernate.cfg.xml中添加对C3P0的配置

		<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
		<property name="hibernate.c3p0.max_size">20</property>
		<property name="hibernate.c3p0.min_size">5</property>
		<property name="hibernate.c3p0.timeout">50000</property>
		<property name="hibernate.c3p0.max_statements">100</property>
		<property name="hibernate.c3p0.idle_test_period">3000</property>
		<!-- 当连接池耗尽并接到获得连接的请求,则新增加连接的数量 -->
		<property name="hibernate.c3p0.acquire_increment">2</property>
		<!-- 是否验证,检查连接 -->
		<property name="hibernate.c3p0.validate">false</property>
这样就已经配置完成了

猜你喜欢

转载自blog.csdn.net/the_programlife/article/details/80555840
今日推荐