Hibernate框架
来源:互联网 发布:知乎 日本整容 编辑:程序博客网 时间:2024/06/10 09:26
Hibernate是一个开放源代码的对象关系映射框架(ORM),它对JDBC进行了非常轻量级的对象封装,简化了java应用程序与数据库交互的开发。简化了数据创建,数据处理和数据访问。
- ①面向对象操作:将对数据库的操作转换为对Java对象的操作。
- ②数据库独立查询:通过配置对应的数据库“方言”,就可以根据不同类型的数据库生成适合的SQL语句。
- ③非侵入式:Hibernate不要求持久化类实现任何接口或继承任何类。
- ④快速性能:Hibernate框架内部使用缓存,支持查询缓存,因此性能很快。
- ⑤自动创建表:Hibernate框架提供了自动创建数据库表的功能。
- ⑥简化复杂连接:在hibernate框架中可轻松获取多个表中的数据。
- ⑦提供查询统计和数据库状态:Hibernate提供有关查询和数据库状态的统计信息。
一、ORM概念
对象关系映射(Object Relational Mapping,简称ORM),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。
把对象表示的映射到基于SQL的关系模型数据库结构中去。在具体的操作实体对象的时候,就不需要再去和复杂的 SQ L 语句打交道,只需简单的操作实体对象的属性和方法。ORM 技术是在对象和关系之间提供了一条桥梁,对象型数据和数据库中的关系型的数据通过这个桥梁来相互转。
ORM技术特点:
- ①提高了开发效率。由于ORM可以自动将对象与数据库中的字段与属性的映射,所以已经不需要一个专用的、庞大的数据访问层。
- ②ORM提供了对数据库的映射,不用sql直接编码,能够像操作对象一样从数据库获取数据。
二、第一个hibernate
(一)Hibernate体系结构
Hibernate架构包括许多对象持久对象,会话工厂,事务工厂,连接工厂,会话,事务等。hibernate架构中有4层Java应用层,持久层,hibernate映射层和数据库层。
(二)引入相关jar包
需要引入hibernate的核心包和数据库连接包。只要到maven公库就能找到相应的jar包。我使用的以下版本:
(三)映射文件(**.hbm.xml)
1、创建实体类。
package org.ssh1.entity;import java.util.Date;/** * 用来封装数据的实体类 * * @author lee * */public class User { private int id; private String name; private Date birthday; //默认构造器 public User() {}; 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; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; }}
2、映射文件
映射文件的名称必须和实体类一样,以 .hbm.xml
结尾。例如上面实体类的映射文件则为 User.hbm.xml 。
<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><!-- 映射文件 package属性:为该映射文件所在的包 --><hibernate-mapping package="org.ssh1.entity"> <!-- 实体类映射 name属性:对应实体类的全称,包名+类名 table属性:对应实体类的 数据库表名 --> <class name="User" table="user"> <!-- 1、主键映射 name属性:实体类的成员变量 type属性:实体类的成员变量的类型 (可以为JAVA的类型 或 hibernate类型) --> <id name="id" type="int"> <!-- 字段映射 name属性:对应数据库的字段的名称 --> <column name="id" /> <!-- 主键的生成策略 --> <generator class="native" /> </id> <!-- 2、普通字段映射 name属性:实体类的成员变量名称 type属性:实体类的成员变量的类型 --> <property name="name" type="java.lang.String"> <!-- 字段映射 name属性:对应数据库的字段的名称 --> <column name="name" /> </property> <property name="birthday" type="java.util.Date"> <column name="birthday" /> </property> </class></hibernate-mapping>
4、创建数据库
例如,上面实体类和数据库的对应
PS:实体类和映射文件必须在同一个包下面
PSPS : 实体类的成员变量 和 数据库的字段 名称可以不一样。
(四)配置文件(**.cfg.xml)
<?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> <!-- 数据库连接配置 --> <!-- 配置文件的问题一定要注意好. hibernate有时候即使是配置错了,在一定的条件下也可以运行。 不要因此出现问题时,而不检查配置文件的问题。 --> <!-- mysql驱动 --> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <!-- url --> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate</property> <!-- 用户名 --> <property name="hibernate.connection.username">root</property> <!-- 密码 --> <property name="hibernate.connection.password">qwertyuio</property> <!-- 配置数据库的方言 根据不同的数据库,配置不同的方言。 通过这种方式,hibernate就可以以面向对象的形式来操作数据库,自动生成对应不同数据库的sql语句。 而不会因为数据库版本的不同而,而需要修改sql语句。 --> <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property> <!-- 是否打印出 执行的sql语句 --> <property name="hibernate.show_sql">true</property> <!-- 配置映射文件 resource属性:包名+映射文件名 file属性:如果不用resource属性,file属性要求是绝对路径。 --> <mapping resource="org/ssh1/entity/User.hbm.xml"></mapping> </session-factory></hibernate-configuration>
(五)使用Hibernate
到了这里基本配置已经完成了。现在我们尝试使用hibernate来想数据库,保存一个对象到数据库中。
1、相关API
在使用hibernate前,我们先了解相关的API。
- (1)Configuration类:负责管理 hibernate配置文件。
- ①Hibernate运行的底层信息:数据库的URL、用户名、密码、JDBC驱动类,数据库Dialect,数据库连接池等(对应 hibernate.cfg.xml 文件)。
②持久化类与数据表的映射关系(*.hbm.xml 文件) - (2)SessionFactory类:
- ①Configuration对象根据当前的配置信息生成 SessionFactory 对象。SessionFactory 对象一旦构造完毕,即被赋予特定的配置信息。
②SessionFactory 对象中保存了当前的数据库配置信息和所有映射关系以及预定义的SQL语句。同时,SessionFactory还负责维护Hibernate的二级缓存。 - (3)Session类
- ①Session是应用程序与数据库之间交互操作的一个单线程对象,是 Hibernate 运作的中心,所有持久化对象必须在 session 的管理下才可以进行持久化操作。此对象的生命周期很短。
②Session 对象有一个一级缓存,显式执行 flush 之前,所有的持久层操作的数据都缓存在 session 对象处。相当于 JDBC 中的 Connection。持久化类与 Session 关联起来后就具有了持久化的能力 - (4)Transaction类
- ①代表一次原子操作,它具有数据库事务的概念。所有持久层都应该在事务管理下进行,即使是只读操作。
②session.beginTransaction() 开启事务
③commit() 提交事务
④rollback() 事务回滚
⑤wasCommitted() 检查事务是否提交
2、使用hibernate
package org.ssh1.dao;import java.util.Date;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.Transaction;import org.hibernate.cfg.Configuration;import org.junit.Test;import org.ssh1.entity.User;public class Dao { @Test public void dao() { //创建Configuratiion对象 Configuration config = new Configuration(); //加载配置文件 //(默认加载 src下的 hibernate.cfg.xml文件,也可以传入路径参数,加载其他的配置文件) config.configure(); //创建一个Session工厂类 SessionFactory sessionFactory = config.buildSessionFactory(); Session session = null; Transaction trans = null; try { //创建一个会话 session = sessionFactory.openSession(); //开启事务 trans = session.beginTransaction(); //创建一个User对象,并添加一些信息 User user = new User(); user.setName("yang"); user.setBirthday(new Date()); //保存对象 //在这里我们可以看到,hibernate封装后的数据库操作,是以对象的形式来操作的 //不需要写任何的sql语句 session.save(user); //提交事务 trans.commit(); }catch(Exception e) { //出现异常,事务回滚 trans.rollback(); throw new RuntimeException(e); }finally { //关闭会话 session.close(); } }}
测试运行一下:
可以看到正确执行了,保存一个User对象到数据库中。hibernate,使程序脱离了繁琐的 JDBC的操作,以操作对象的形式来操作数据库。
PS:可能出现的异常:
Field ‘id’ doesn’t have a default value
数据库表中的主键没设置自动增长。也可以将主键的配置<generator class="native"/>
改为<generator class="assigned"/>
。
assigned是指主键是由人工分配的,native则指主键值由库自动给出。
三、hibernate 常用API
这里主要讲解如何使用 Session的方法来操作数据库。(相关的映射文件、配置文件、实体类、数据库和上面一样。)
(一)这里将hibernate的加载配置的方法,写到一个hibernate工具类中,方便我们使用。
package org.ssh1.utils;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.cfg.Configuration;/** * hibernate工具类 * * @author lee * */public class HibernateUtils { public static SessionFactory sessionFactory ; static { Configuration config = new Configuration(); config.configure(); sessionFactory = config.buildSessionFactory(); } public static Session openSession() { return sessionFactory.openSession(); }}
(二)使用相关的API
package org.ssh1.dao;import java.util.Date;import org.hibernate.Session;import org.hibernate.Transaction;import org.junit.Test;import org.ssh1.entity.User;import org.ssh1.utils.HibernateUtils;/** * 相关的hibernate API 使用 * * @author lee * */public class Dao { //1、save 保存对象(数据)方法 @Test public void testSave(){ Session session = null; Transaction trans = null; try { session = HibernateUtils.openSession(); trans = session.beginTransaction(); //因为id主键为自动增长,因此不需要指定id属性 User user = new User(); user.setName("qing"); user.setBirthday(new Date()); System.out.println("1、将一个对象保存到数据库当中:"); session.save(user); trans.commit(); }catch(Exception e){ trans.rollback(); throw new RuntimeException(e); }finally { session.close(); } } //2、update 更新对象(数据)方法 @Test public void testUpdate(){ Session session = null; Transaction trans = null; try { session = HibernateUtils.openSession(); trans = session.beginTransaction(); //更新必须要有主键,当成员变量为null的时候,也会将对应的字段更新为null //例如:下面的User对象没有设置 birthday属性,当执行更新操作,可以看到该条数据的birthday字段为null User user = new User(); user.setId(100); user.setName("xiao"); System.out.println("2、将指定id值的对象 更新到数据库中:"); session.update(user); trans.commit(); }catch(Exception e){ trans.rollback(); throw new RuntimeException(e); }finally { session.close(); } } //3、get 获取对象(数据)方法 (主键查询) @Test public void testGet(){ Session session = null; Transaction trans = null; try { session = HibernateUtils.openSession(); trans = session.beginTransaction(); //要查询对象(数据)的 id值 int id = 1; System.out.println("3、根据 id 值获取指定的对象(数据):"); User user = session.get(User.class, id); trans.commit(); }catch(Exception e){ trans.rollback(); throw new RuntimeException(e); }finally { session.close(); } } //4、load 获取对象(数据)方法 (主键查询)(懒加载,就是用到时才会去查询。) @Test public void testLoad(){ Session session = null; Transaction trans = null; try { session = HibernateUtils.openSession(); trans = session.beginTransaction(); //要查询对象(数据)的 id值 int id = 1; System.out.println("4、根据 id 值获取指定的对象(数据):"); User user = session.load(User.class, id); user.getName();//这时候才会去数据库中查找数据(懒加载) trans.commit(); }catch(Exception e){ trans.rollback(); throw new RuntimeException(e); }finally { session.close(); } } //5、saveOrUpdate 保存或更新对象(数据)方法 @Test public void testSaveOrUpdate(){ Session session = null; Transaction trans = null; try { session = HibernateUtils.openSession(); trans = session.beginTransaction(); //当该 对象的id值对应的数据,在数据库中存在时,则更新对象 //当该 对象没有设置id值 ,或id值对应的数据,在数据库中不存在时,则保存对象 User user = new User(); user.setId(99); System.out.println("5、保存或更新一个对象(数据):"); session.saveOrUpdate(user); trans.commit(); }catch(Exception e){ trans.rollback(); throw new RuntimeException(e); }finally { session.close(); } } //6、delete 删除对象(数据)方法 @Test public void testSaveOrUpdate(){ Session session = null; Transaction trans = null; try { session = HibernateUtils.openSession(); trans = session.beginTransaction(); //以传入一个id值来删除指定的对象(数据) int id = 88; System.out.println("6、删除一个对象(数据):"); session.delete(id); trans.commit(); }catch(Exception e){ trans.rollback(); throw new RuntimeException(e); }finally { session.close(); } }}
测试运行一下,可以看到结果:
四、hibernate 查询方法
hibernate的查询方式常见的主要分为三种: HQL查询,QBC(Criteria)查询,以及使用原生SQL查询。
(一)HQL查询(推荐使用)
HQL(Hibernate Query Language)是hibernate提供的面向对象的查询语言,在HQL中使用类名,而不是表名。所以是数据库独立的查询语言。
HQL查询提供了更加丰富的和灵活的查询特性,因此Hibernate将HQL查询方式立为官方推荐的标准查询方式,HQL查询在涵盖Criteria查询的所有功能的前提下,提供了类似标准SQL语句的查询方式,同时也提供了更加面向对象的封装。
HQL有很多优点。 它们如下:
- 数据库独立
- 支持多态查询
- 易于Java程序员学习
1、常用API
HQL查询主要是调用 Query对象的方法来实现。Query的对象可以通过Session接口调用createQuery()方法。常用的方法有:
//获取一个Query对象Query query = session.creaeteQuery("HQL语句");//将获取的结果作为列表返回public List list()//指定从哪里检索数据public Query setFirstResult(int rowno) //指定从表中检索数据的行数public Query setMaxResult(int rowno) //设置占位符的值public Query setParameter(int position, Object value) //设置占位符的值public Query setParameter(String name, Object value)
2、常用的HQL查询方式
这里,我们介绍下一些常用的查询。
(查询所有、条件查询)(单个字段查询、单列查询、多列查询)(统计查询、分页查询)
package org.ssh1.dao;import java.util.List;import org.hibernate.Session;import org.hibernate.Transaction;import org.hibernate.query.Query;import org.junit.Test;import org.ssh1.entity.User;import org.ssh1.utils.HibernateUtils;/** * 常用的HQL查询 * * @author lee * */public class Dao { //1、查询所有 @Test public void getAll() { Session session = null; Transaction trans = null; try { session = HibernateUtils.openSession(); trans = session.beginTransaction(); /* * 类似于SQL语句,但是通过操作对象来实现的。 * 例如,"from User" 中,"User" 不是数据表的名称,而是实体类的名称。 * 相对于sql语句 (select * from user) 来,还可以略写 "select * " * */ //HQL语句 ,获取所有的 User对象 String HQL = "from User"; //创建一个Query类 @SuppressWarnings("unchecked") Query<User> query = session.createQuery(HQL); //将获取的结果作为列表返回 List<User> users = query.list(); //输出从数据库获得的结果 System.out.println(users); trans.commit(); }catch(Exception e) { trans.rollback(); throw new RuntimeException(e); }finally { session.close(); } } //2、条件查询 @Test public void getPart() { Session session = null; Transaction trans = null; try { session = HibernateUtils.openSession(); trans = session.beginTransaction(); /** * 这里还有很多的条件查询,这里只是作为一个举例 * */ //HQL语句 ,获取字段 name为指定的值的 User对象 String HQL = "from User where name = ?"; //创建一个Query类 @SuppressWarnings("unchecked") Query<User> query = session.createQuery(HQL); //设置第 1 个占位符的值(从0开始) query.setParameter(0, "lee"); //query.setParameter("name","lee")//这种形式也是允许的 //获取 单一的一个 查询到的数据 User user = query.uniqueResult(); //输出从数据库获得的结果 System.out.println(user); trans.commit(); }catch(Exception e) { trans.rollback(); throw new RuntimeException(e); }finally { session.close(); } } //3、单个字段查询 @Test public void getSingleProperty() { Session session = null; Transaction trans = null; try { session = HibernateUtils.openSession(); trans = session.beginTransaction(); /** * 这里还有很多的单个字段查询,这里只是作为一个举例 * */ //HQL语句 ,获取指定 id值的对象的 name字段 String HQL = "select u.name from User u where id = ?"; //创建一个Query类 @SuppressWarnings("unchecked") Query<String> query = session.createQuery(HQL); //设置第 1 个占位符的值(从0开始) query.setParameter(0, 1); //获取 单一的一个 查询到的数据 String name = query.uniqueResult(); //输出从数据库获得的结果 System.out.println(name); trans.commit(); }catch(Exception e) { trans.rollback(); throw new RuntimeException(e); }finally { session.close(); } } //4、单列查询 @Test public void getSingleColumn() { Session session = null; Transaction trans = null; try { session = HibernateUtils.openSession(); trans = session.beginTransaction(); /** * 这里还有很多的单列查询,这里只是作为一个举例 * */ //HQL语句 ,获取所有User对象的 name 字段 String HQL = "select u.name from User u "; //创建一个Query类 @SuppressWarnings("unchecked") Query<String> query = session.createQuery(HQL); //获取 多个查询到list集合 List<String> names = query.list(); //输出从数据库获得的结果 System.out.println(names); trans.commit(); }catch(Exception e) { trans.rollback(); throw new RuntimeException(e); }finally { session.close(); } } //5、多列查询 @Test public void getColumns() { Session session = null; Transaction trans = null; try { session = HibernateUtils.openSession(); trans = session.beginTransaction(); /** * 这里还有很多的多列查询,这里只是作为一个举例 * */ //HQL语句 ,获取所有User对象的 name 、id字段 String HQL = "select u.name,u.id from User u "; //创建一个Query类 @SuppressWarnings("unchecked") Query<Object> query = session.createQuery(HQL); //获取 多个查询到list集合 List<Object> results = query.list(); //输出从数据库获得的结果 //因为其返回的是一个集合,集合里面装的每一个元素是数组。 for(Object result :results ) { Object[] res = (Object[]) result; System.out.println(res[1]+" "+res[0]); } trans.commit(); }catch(Exception e) { trans.rollback(); throw new RuntimeException(e); }finally { session.close(); } } //6、统计查询 @Test public void getSum() { Session session = null; Transaction trans = null; try { session = HibernateUtils.openSession(); trans = session.beginTransaction(); /** * 这里还有很多的统计查询,这里只是作为一个举例 * */ //HQL语句 ,获取 数据的总数 String HQL = "select count(*) from User"; //创建一个Query类 @SuppressWarnings("unchecked") Query<Long> query = session.createQuery(HQL); //获取 单一的一个 查询到的数据 Long count = query.uniqueResult(); //输出从数据库获得的结果 System.out.println(count); trans.commit(); }catch(Exception e) { trans.rollback(); throw new RuntimeException(e); }finally { session.close(); } } //7、分页查询 @Test public void getParts() { Session session = null; Transaction trans = null; try { session = HibernateUtils.openSession(); trans = session.beginTransaction(); /** * 这里还有很多的分页查询,这里只是作为一个举例 * */ //HQL语句 ,获取所有的 User对象 String HQL = "from User"; //创建一个Query类 @SuppressWarnings("unchecked") Query<User> query = session.createQuery(HQL); //从第 2 行开始查询 query.setFirstResult(2); //查询 10 行数据 query.setMaxResults(10); //获取 单一的一个 查询到的数据 List<User> users = query.list(); //输出从数据库获得的结果 System.out.println(users); trans.commit(); }catch(Exception e) { trans.rollback(); throw new RuntimeException(e); }finally { session.close(); } }}
(二)Criteria查询
Criteria(QBC query by criteria,完全面向对象的查询)提供了一种面向对象的方式查询数据库。
package org.ssh1.dao;import java.util.List;import org.hibernate.Criteria;import org.hibernate.Session;import org.hibernate.Transaction;import org.hibernate.criterion.Restrictions;import org.junit.Test;import org.ssh1.entity.User;import org.ssh1.utils.HibernateUtils;/** * * Criteria查询(只做简单的介绍) * 更多关于Criteria查询可以查看其 API,进行更深度的学习 * * @author lee * */public class CriteriaDao { //1、获取所有的 User对象 @Test public void getAll() { Session session = null; Transaction trans = null; try { session = HibernateUtils.openSession(); trans = session.beginTransaction(); //可以看到 criteria的查询中 看到任何的类似sql的语句,完全地面向对象开发 //但是需要了解很多的API //传入一个 类的class属性 Criteria qbc = session.createCriteria(User.class); //获取所有 @SuppressWarnings("unchecked") List<User> list = qbc.list(); //输出获取的结果集 System.out.println(list); trans.commit(); }catch(Exception e) { trans.rollback(); throw new RuntimeException(e); }finally { session.close(); } } //2、条件查询 @Test public void getPart() { Session session = null; Transaction trans = null; try { session = HibernateUtils.openSession(); trans = session.beginTransaction(); //传入一个 类的class属性 Criteria qbc = session.createCriteria(User.class); //获取指定 id 值的User qbc.add(Restrictions.eq("id", 1)); @SuppressWarnings("unchecked") User user = (User) qbc.uniqueResult(); //输出获取的结果集 System.out.println(user); trans.commit(); }catch(Exception e) { trans.rollback(); throw new RuntimeException(e); }finally { session.close(); } }}
(三)本地SQL查询
多用于使用于复杂的查询,就是使用原生态的sql查询。(不能跨数据库平台)
package org.ssh1.dao;import java.util.List;import org.hibernate.SQLQuery;import org.hibernate.Session;import org.hibernate.Transaction;import org.junit.Test;import org.ssh1.entity.User;import org.ssh1.utils.HibernateUtils;/** * * SQL查询(只做简单的介绍) * 更多关于SQL查询可以查看其 API,进行更深度的学习 * * @author lee * */public class CriteriaDao { //1、获取所有的 User对象 @SuppressWarnings("deprecation") @Test public void getAll() { Session session = null; Transaction trans = null; try { session = HibernateUtils.openSession(); trans = session.beginTransaction(); //传入一个 sql 语句 SQLQuery sql = session.createSQLQuery("select * from user"); //获取所有 @SuppressWarnings("unchecked") List<User> list = sql.list(); //输出获取的结果集 System.out.println(list); trans.commit(); }catch(Exception e) { trans.rollback(); throw new RuntimeException(e); }finally { session.close(); } } //2、条件查询 @SuppressWarnings("deprecation") @Test public void getPart() { Session session = null; Transaction trans = null; try { session = HibernateUtils.openSession(); trans = session.beginTransaction(); //传入一个sql语句 SQLQuery sql = session.createSQLQuery("select * from user where id=1"); @SuppressWarnings("unchecked") User user = (User) sql.uniqueResult(); //输出获取的结果集 System.out.println(user); trans.commit(); }catch(Exception e) { trans.rollback(); throw new RuntimeException(e); }finally { session.close(); } }}
PS:编写 hibernate的 映射文件 和 配置文件,要自己编写过于麻烦。可以在开发集成环境中,添加在 JBoss Tools插件,来帮助我们。
- Hibernate框架
- Hibernate框架
- Hibernate框架
- hibernate 框架
- hibernate框架
- hibernate框架
- Hibernate框架
- Hibernate框架
- Hibernate框架
- Hibernate框架
- Hibernate框架
- hibernate框架
- hibernate框架
- hibernate 框架
- Hibernate框架
- Hibernate框架
- Hibernate框架
- Hibernate框架
- 技能提升
- nim博弈讲解(转载)
- Phoenix 使用脚本方式导入 hbase
- RxJava 与 Retrofit 结合的最佳实践
- 【LeetCode】1. Two Sum
- Hibernate框架
- NYOJ 104 最大和
- BZOJ[1051][HAOI2006]受欢迎的牛 Tarjan缩点
- FoldLineView折线图
- ARM Linux系统调用的原理
- easyui双击弹框后在新的datagrid中加合计列
- 封装caffe-windows-master为动态链接库
- LNMP(yum和源码)
- AOP面向切面编程的简单动态代理实现