Hibernate
轻量级、持久层、ORM,Hibernate 是一款全自动的 ORM 框架。
ORM
ORM 是一种自动生成 SQL 语句的技术,它可以将对象中的数据自动存储到数据库中,也可以反过来将数据库中的数据自动提取到对象中,整个过程不需要人工干预,避免了手写 SQL 带来的麻烦
- Object:对象
- Relation:关系型数据库
- Mapping:映射
Hibernate与MyBatis的比较
缓存机制
Hibernate 提供了缓存机制(一级缓存、二级缓存、查询缓存),我们可以将那些经常使用的数据存放到 Hibernate 缓存中。当 Hibernate 在查询数据时,会优先到缓存中查找,如果找到则直接使用,只有在缓存中找不到指定的数据时,Hibernate 才会到数据库中检索,因此 Hibernate 的缓存机制能够有效地降低应用程序对数据库访问的频次,提高应用程序的运行性能。
版本
-
hibernate3.x -
hibernate4.x -
hibernate5.x
搭建hibernate环境
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<hibernate.version>5.4.1.Final</hibernate.version>
<hibernate-validator.version>6.0.13.Final</hibernate-validator.version>
<mysql.version>5.1.47</mysql.version>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>${hibernate-validator.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.url">
jdbc:mysql://localhost:3306/video
</property>
<property name="connection.username">root</property>
<property name="connection.password">123456</property>
<property name="connection.driver_class">
com.mysql.jdbc.Driver
</property>
<property name="dialect">
org.hibernate.dialect.MySQL5Dialect
</property>
<property name="show_sql">true</property>
<property name="current_session_context_class">thread</property>
<property name="hibernate.format_sql">true</property>
<mapping resource="Admin.hbm.xml"/>
</session-factory>
</hibernate-configuration>
<?xml version='1.0' encoding='utf-8'?>
<!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="net.biancheng.www.po.User" table="user">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="userId" column="user_id" type="java.lang.String"/>
<property name="userName" column="user_name"/>
<property name="password" column="password"/>
<property name="email" column="email"/>
</class>
</hibernate-mapping>
关联映射
常用主键生成策略
-
assigned 主键由外部程序负责生成,在 save() 之前必须指定一个,Hibernate不负责维护主键生成。也就是可以每次指定主键。该方式不推荐 -
increment 这种方式在每次插入前,需要通过“select max(主键) from 表名 ”这种方式先查询最大ID,然后通过ID+1来作为新的主键值。这种方式也不推荐,因为这样会出现线程安全问题。 -
identity identity由底层数据库生成标识符。identity是由数据库自己生成的,但这个主键必须设置为自增长,使用identity的前提条件是底层数据库支持自动增长字段类型,如DB2、SQL Server、MySQL、Sybase和HypersonicSQL等,Oracle这类没有自增字段的则不支持。 -
sequence 采用数据库提供的sequence机制生成主键,需要数据库支持sequence。如oralce、DB、SAP DB、PostgerSQL、McKoi中的sequence。MySQL这种不支持sequence的数据库则不行 hibernate3可指定使用哪个序列,hibernate5 为hibernate_sequence -
hilo hilo(高低位方式high low)是hibernate中最常用的一种生成方式,需要一张额外的表保存hi的值。保存hi值的表至少有一条记录(只与第一条记录有关),否则会出现错误。可以跨数据库。 -
native native由hibernate根据使用的数据库自行判断采用identity、hilo、sequence其中一种作为主键生成方式,灵活性很强。如果能支持identity则使用identity,如果支持sequence则使用sequence。 -
uuid UUID:Universally Unique Identifier,是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的。按照开放软件基金会(OSF)制定的标准计算,用到了以太网卡地址、纳秒级时间、芯片ID码和许多可能的数字,标准的UUID格式为:xxxxxxxx-xxxx-xxxx-xxxxxx-xxxxxxxxxx (8-4-4-4-12)
级联操作
一对多
<hibernate-mapping>
<class name="com.ishangu.model.Category" table="t_category">
<id name="cid" column="cid">
<generator class="native"/>
</id>
<property name="cname" column="cname"/>
<set name="products" cascade="save-update">
<key column="cid"/>
<one-to-many class="com.ishangu.model.Product"/>
</set>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="com.ishangu.model.Product" table="t_product">
<id name="pid" column="pid">
<generator class="native"/>
</id>
<property name="pname" column="pname"/>
<property name="price" column="price"/>
<many-to-one name="category" class="com.ishangu.model.Category" column="cid"/>
</class>
</hibernate-mapping>
@Test
public void oneAndMany(){
Session session = HibernateUtil.getSession();
Transaction transaction = session.beginTransaction();
Category category = new Category();
category.setCname("水果");
Product product = new Product();
product.setPname("苹果");
product.setPrice(10);
category.getProducts().add(product);
product.setCategory(category);
session.save(category);
transaction.commit();
session.close();
}
@Test
public void del(){
Session session = HibernateUtil.getSession();
Transaction transaction = session.beginTransaction();
Category category = session.get(Category.class, 2);
session.delete(category);
transaction.commit();
session.close();
}
多对多
普通
<hibernate-mapping>
<class name="com.ishangu.model.Student" table="student">
<id name="sid" column="sid">
<generator class="native"/>
</id>
<property name="sname" column="sname"/>
<set name="courses" table="sc">
<key column="sid"/>
<many-to-many column="cid" class="com.ishangu.model.Course"/>
</set>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="com.ishangu.model.Course" table="course">
<id name="cid" column="cid">
<generator class="native"/>
</id>
<property name="cname" column="cname"/>
<set name="students" table="sc">
<key column="cid"/>
<many-to-many column="sid" class="com.ishangu.model.Student"/>
</set>
</class>
</hibernate-mapping>
@Test
public void add(){
Session session = HibernateUtil.getSession();
Transaction transaction = session.beginTransaction();
Student s1 = new Student();
s1.setSname("张三");
Student s2 = new Student();
s2.setSname("李四");
Course c1 = new Course();
c1.setCname("前端");
Course c2 = new Course();
c2.setCname("后端");
Course c3 = new Course();
c3.setCname("Java");
s1.getCourses().add(c1);
s1.getCourses().add(c2);
s2.getCourses().add(c1);
s2.getCourses().add(c3);
c1.getStudents().add(s1);
c2.getStudents().add(s1);
c2.getStudents().add(s2);
c3.getStudents().add(s2);
session.save(s1);
session.save(s2);
session.save(c1);
session.save(c2);
session.save(c3);
transaction.commit();
session.close();
}
级联
外键维护
一对多
<set name="products" cascade="save-update" inverse="true">
<key column="cid"/>
<one-to-many class="com.ishangu.model.Product"/>
</set>
@Test
public void foreignKey(){
Session session = HibernateUtil.getSession();
Transaction transaction = session.beginTransaction();
Product product = session.get(Product.class, 1);
Category category = session.get(Category.class, 1);
product.setCategory(category);
category.getProducts().add(product);
transaction.commit();
session.close();
}
多对多
HQL查询
@Override
public List<House> getAllHouse() {
Session session = HibernateUtil.getSession();
Transaction transaction = session.beginTransaction();
List house = session.createQuery("from House").list();
return house;
}
@Test
public void selectAllStreet(){
HouseDao houseDao = new HouseDaoImpl();
List<House> allHouse = houseDao.getAllHouse();
for (House h:allHouse
) {
System.out.println(h);
}
}
@Override
public List<House> pageInfo(int pageSize, int pageNumber) {
Session session = HibernateUtil.getSession();
Transaction transaction = session.beginTransaction();
Query query = session.createQuery("from House");
query.setFirstResult(pageSize);
query.setMaxResults(pageNumber);
List<House> list = query.list();
transaction.commit();
return list;
}
HouseDao houseDao = new HouseDaoImpl();
List<House> houses = houseDao.pageInfo(1, 5);
for (House h:houses
) {
System.out.println(h);
}
hibernate的DQL操作
1:创建配置对象 2:读取配置文件 3:创建session工厂 4:获取session对象 5:具体查询操作 6:关闭session 7:关闭工厂
hibernate的DML操作
1:创建配置对象 2:读取配置文件 3:创建session工厂 4:获取session对象 5:获取事务 5:具体DML 6:提交事务 7:关闭session 8:关闭工厂
hibernate默认使用占位符形式代替参数
hbm2ddl.auto 的值
update: 1:每次使用hibernate的时候会自动检查如果表不存在则会自动创建表结构 2:每次使用hibernate的时候会自动检查,如果表中的列与xml映射不符合,会自动增加表中不存在的列(并不会删除表中存在 但是xml中没有的列) create: 每次启动hibernate都会先删除表结构,然后再次创建表后执行sql create-drop: 1:每次使用完hibernate后都会直接把表删掉 2:注意:只有在session工厂正常关闭的情况下才会执行最后的删除表操作 validate: 用于检查mapper与数据库表是否一致,如果不一致则直接抛异常
hibernate 主键自增策略
1:native 使用数据库本地主键生成策略 mysql=auto_increment oracle = sequence
2:uuid 使用uuid作为表的主键,需要主键类型必须是String(varchar(varchar2))
3:identity 使用数据库本地主键生成策略 mysql=auto_increment ,oracle不支持
4:sequence 使用序列作为主键(如果只配置sequence 则会自动创建一个序列叫 hibernate_sequence)mysql不支持
5:increment 会先查询当前ID的最大值,然后在上面+1(与mysql的自增长没有任何的关系)
6:tableGenerator 使用序列生成器,使用一张表来模拟序列操作,会造成很多额外sql浪费。
hibernate四种状态:(根据OID区别)
1:临时状态(瞬时态) 刚刚使用new出来的对象,没有被持久化,不再session中,没有OID 2:持久态 对象已经被持久化,加入到session的缓存中,有OID 3:游离态(托管态) 对象已经被持久化,不在session的缓存中,hibernate在提交事务的时候会自动关闭session所以事务提交后对象自动 转为游离态 4:删除状态 对象由OID,并且在session的管理中,但是已经有计划删除
getCurrentSession() 与openSession的区别
openSession 是每次都打开一个全新的session 而getCurrentSession 是从当前线程中获取session,如果当前线程不存在session的话,会使用openSession创建一个session并绑定到当前线程中。使用getCurrentSession 需要在hibernate的配置文件中配置: thread
session对象(缓存是以map的形式存在)
1:session对象包含了很多操作数据库的方法 2:session的线程是不安全的,所以session的声明周期为(在web中)一次请求request 3:session是有一级缓存的,在一次生命周期内,获得相同类型,相同OID的对象只会发送1次sql 4:session查询出来的对象,都会放到缓存中管理 5:清楚session对象的方法,clear() 清空所有对象 session.evict(user); 清除缓存指定对象
hibernate 中查询叫做HQL查询
select 后面跟着的是model类的列名,必须与model类列名一致(大小写一致) from 后面跟着的是model类名,大小写要求一致
hibernate中get与load的区别
- 如果未能发现符合条件的记录,get方法返回null,而load方法会抛出一个ObjectNotFoundException
- Load方法可返回实体的代理类实例,而get方法永远直接返回实体类
- load方法可以充分利用内部缓存和二级缓存中的现有数据,而get方法则仅仅在内部缓存中进行数据查找,如果没有发现符合条件的数据,将越过二级缓存,直接调用SQL完成数据读取
|