理解
一、Hibernate是对JDBC进一步封装
原来没有使用Hibernate做持久层开发时,存在很多冗余,如:各种JDBC语句,connection的管理,所以出现了Hibernate把JDBC封装了一下,我们不用操作数据,直接操作它就行了。
二、我们再从分层的角度来看
我们知道非常典型的三层架构:表示层,业务层,还有持久层。Hiberante也是持久层的框架,而且持久层的框架还有很多,比如:IBatis,Nhibernate,JDO,OJB,EJB等等。
三、Hibernate是开源的一个ORM(对象关系映射)框架。
ORM,即Object-Relational Mapping,它的作用就是在关系型数据库和对象之间做了一个映射。从对象(Object)映射到关系(Relation),再从关系映射到对象。这样,我们在操作数据库的时候,不需要再去和复杂SQL打交道,只要像操作对象一样操作它就可以了(把关系数据库的字段在内存中映射成对象的属性)。
总结:省略了mybatis中需要写的mapper文件,但同时由于每次操作需要生成一句sql语句,所以不适合大量数据的使用。
使用
1. maven依赖
org.hibernate – hibernate-core
org.hibernate.javax.persistence – hibernate-jpa-2.1-api
org.hibernate.common – hibernate-commons-annotation
com.fasterxml - classmate
org.apache.geronimo.specs – geronimo-annotations_1.0_spec
org.jboss – jandex
org.jboss.logging – jboss-logging
jboss - javassist
2. 配置文件(hibernate.cfg.xml)
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 四大参数 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver(驱动)</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate(数据库)</property>
<property name="hibernate.connection.username">用户名</property>
<property name="hibernate.connection.password">密码</property>
<!-- SQL 方言 ,注意使用MySQLInnoDBDialect,才可以使用Innodb引擎-->
<property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<!-- 打印出sql -->
<property name="show_sql">true</property>
<!-- 格式化sql -->
<property name="format_sql">true</property>
<!-- 有表更新表,没有表自动创建表 -->
<property name="hbm2ddl.auto">update</property>
<!-- 加载映射文件 -->
<mapping resource="xml文件路径"/>或
<mapping class="类路径"/>
</session-factory>
</hibernate-configuration>
3. 实体类写法
- xml配置文件
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.hibernate.entity.User" table="user">
<id name="uid" column="uid">
<!-- 使用数据库默认的生成主键的方案 -->
<generator class="native"/>
</id>
<property name="username" column="username"/>
<property name="password" column="password"/>
</class>
</hibernate-mapping>
- JPA
什么是JPA?
Java Persistence API,Java在持久层的一套接口,与JDBC接口类似,提供一套规范,有其他数据库厂商去实现。Hibernate实现了JPA接口。


注解在实体类的使用:
@Entity //表示该类为持久化类
@Table(name="user") //对应数据库的表名,默认为类名小写
public class User {
@Id //主键
@GeneratedValue(strategy=GenerationType.IDENTITY)//主键生成策略 IDENTITY与native类似,默认为auto
private Integer uid;
@Column(name="user_name") //设置属性名与字段名的映射关系,默认同属性名
private String username;
private String password; //如果属性名与字段名一致,可以不写注解
@OneToMany(cascade=CascadeType.ALL) //一对多,casacde为级联
@JoinColumn(name="外键名") //外键
private Set<Customer> custSet = new HashSet<>();
@ManyToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY)//多对多,懒加载
@JoinTable(//生成第三张表
name="user_role",//表名如双向则两个类中设置为一样
joinColumns={@JoinColumn(name="uid")},//本表中的主键
inverseJoinColumns={@JoinColumn(name="rid")}//另一张表的主键
)
private Set<Role> roleSet = new HashSet<>();
}
4. SESSION查用API
save、delete、update、get、load
延迟查询:如果使用了对象中非id的属性时才会发送sql语句
saveOrUpdate
瞬时态执行save(),游离态执行update()
merge
两个相同id的对象合并
5. 实体类的三种状态
- 瞬时态:无id,与session无关联,与数据库无关联
- 持久态:有id,与session有关联,与数据库关联 持久态对象修改数据,会自动修改数据库的数据
- 游离态(离线):有id,与session无关联,与数据库有关

6. 测试
Configuration configure = new Configuration().configure("hibernate.cfg.xml");//如果配置文件名如此写法,可以省略
SessionFactory factory = configure.buildSessionFactory();
Session session = factory.openSession();// 获取连接
// 除查询外,更新、删除、添加均需开启事务
Transaction tx = session.beginTransaction();
User user = new User("Steve", "666");
session.save(user);
tx.commit();// 提交事务
session.close();// 关闭连接
增强
1. hql查询
// ---------------占位符条件查询------------------
// 占位符条件查询 ?
public void test3() {
String hql = "from User u where u.username=? and u.password=?";
Query<User> query = session.createQuery(hql);
query.setParameter(0, "lisi");
query.setParameter(1, "123");
User u = query.uniqueResult();
System.out.println(u);
}
// 命名占位符条件查询1 parameter
public void test4() {
String hql = "from User where username=:username and password=:password";
Query<User> query = session.createQuery(hql);
query.setParameter("username", "lisi");
query.setParameter("password", "123");
User u = query.uniqueResult();
System.out.println(u);
}
// 命名占位符条件查询2 javabean或map
public void test5() {
String hql = "from User where username=:username and password=:password";
Query<User> query = session.createQuery(hql);
User user = new User("lisi", "123");
query.setProperties(user);
User u = query.uniqueResult();
}
// 迫切内连接,直接封装成对象 查询custid=1的用户
public void test12() {
String hql = "from User u inner join fetch u.custSet c where c.custid=1";
Query<User> query = session.createQuery(hql);
List<User> list = query.getResultList();
}
其他查询
SQLQuery
Criteria
2. 二级缓存
Hibernate中的二级缓存是属于SessionFactory级别的缓存机制。第一级别的缓存是Session级别的缓存,是属于事务范围的缓存,由Hibernate管理,一般无需进行干预。第二级别的缓存是SessionFactory级别的缓存,是属于进程范围的缓存。
二级缓存也分为了两种:
- 内置缓存:Hibernate自带的,不可卸载,通常在Hibernate的初始化阶段,Hibernate会把映射元数据和预定义的SQL语句放置到SessionFactory的缓存中。该内置缓存是只读的。
- 外置缓存:通常说的二级缓存也就是外置缓存,在默认情况下SessionFactory不会启用这个缓存插件,外置缓存中的数据是数据库数据的复制,外置缓存的物理介质可以是内存或者硬盘。

依赖
org.hibernate – hibernate-ehcache
net.sf.ehcache – ehcache-core
配置文件
<ehcache>
<!--
指定二级缓存存放在磁盘上的位置,可以使用磁盘目录
也可以使用Java System Property目录
user.home是用户目录
user.dir是用户当前工作目录
java.io.tmpdir是默认临时文件路径
name:Cache的唯一标识。
maxElementsInMemory:内存中最大缓存对象数。
eternal:Element是否永久有效,一旦设置true,timeout将不起作用。
timeToIdleSeconds:设置Element在失效前的允许闲置时间。仅当element不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
timeToLiveSeconds:设置Element在失效前允许存活时间。最大时间介于创建时间和失效时间之间。仅当element不是永久有效时使用,默认是0.,也就是element存活时间无穷大。
overflowToDisk:配置此属性,当内存中Element数量达到maxElementsInMemory时,Ehcache将会Element写到磁盘中。
maxElementsOnDisk:磁盘中最大缓存对象数,若是0表示无穷大。
memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略
去清理缓存中的内容。默认策略是LRU(最近最少使用),你也可以设置为FIFO(先进先出)或是LFU(较少使用)
-->
<diskStore path="java.io.tmpdir/cache"/>
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
<!--可以给每个实体类指定一个配置文件,通过name属性指定,要使用类的全名-->
<!--<cache name="com.teemo.entity.User"-->
<!--maxElementsInMemory="10000"-->
<!--eternal="false"-->
<!--timeToIdleSeconds="300"-->
<!--timeToLiveSeconds="600"-->
<!--overflowToDisk="true"-->
<!--/>-->
<cache name="simple"
maxElementsInMemory="1000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
</ehcache>
在spring-hibernate.xml中的配置
<!-- 开启二级缓存:根据id来查询 -->
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<!-- 开启查询缓存:根据非id来查询,需要在query中设置setCacheable(true) -->
<prop key="hibernate.cache.use_query_cache">true</prop>
<!-- 高速缓存提供程序 -->
<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</prop>
在需要使用二级缓存的类上添加注解
@org.hibernate.annotations.Cache(region ="simple",usage = CacheConcurrencyStrategy.READ_ONLY)
网友评论