Hibernate(一)
1.1Hibernate框架概述
1.1.1什么是Hibernate?
- Hibernate是轻量级JavaEE应用的持久层解决方案,是一个关系数据库ORM框架。
- ORM就是通过将Java对象映射到数据库表,通过操作Java对象,就可以完成对数据表的操作。
- Hibernate提供了对关系型数据库增删改查操作
- 流行数据库框架
- JPA Java Persistence API,JPA通过jdk5.0注解或者Xml文件描述对象-关系表的映射关系(只有接口规范)。
- Hibernate最流行的ORM框架,通过对象-关系映射配置,完全脱离底层SQL。
- MyBatis 本来是Apache的一个开源项目iBatis,支持普通SQL查询,存储过程和高级映射的优秀持久层框架。
- Apache DBUtils、Spring JDBC Template。
1.1.2 为什么要使用Hibernate?
- Hibernate对JdbC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。
- Hibernate是一个基于jdbC的主流持久层框架,是一个优秀的ORM实现,它很大程度的简化了DAO层编码工作。
- Hibernate使用Java反射技术,而不是字节码增强程序类实现。
- Hibernate的性能非常好,因为它是一个轻量级框架。映射的灵活性很出色,它支持很多关系型数据库,支持从一对一到多对多各种复杂关系。
1.1.3Hibernate的版本?
- Hibernate3.x版本和Hibernate4.x版本,目前企业中常用的版本是Hibernate3.x版本。
1.2Hibernate的日志记录
1.2.1什么是日志?
日志:程序开发中的一些信息。
- 开发阶段的调试信息。
- 运行时的日志记录,日志代码占代码总量的4%。
1.2.2常用的信息输出?
System.out.println("");
这种方式不好,如果输出的内容比较多,项目已经开发完毕,不想使用输出,需要将每个类中的输出代码注释。
1.2.3Hibernate中使用slf4j技术来实现日志记录
slf4j:简单日志门面(simple logging facade for java),不是具体的日志解决方案,它只服务于各种各样的日志系统。
- 换句话说,就是用于整合其他日志系统。
在企业中常用的日志记录:Log4j。
- 是具体的日志记录方案。
Log4j的日志级别?
- fatal(致命的)、error(普通错误)、warn(警告)、info(信息)、debug(调试)、trace(堆栈)
- 通过配置文件的形式,显示错误信息
- 如果配置的级别是info,那么debug和trace级别的信息不会显示,而fatal、error、warn和info级别的信息会显示。
Log4j的三个组件:
- 记录器(Loggers)
- 格式:记录器=级别,输出源1,输出源2
- log4j.rootLogger=info, stdout
- 输出源(Appenders)
- log4j.appender.stdout=org.apache.log4j.ConsoleAppender :控制台进行输出。
- log4j.appender.file=org.apache.log4j.FileAppender :向文件进行输出。
- 布局(Layouts)
- log4j.appender.stdout.layout=org.apache.log4j.PatternLayout :控制台布局
- log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n :控制台布局的形式
- log4j.appender.file.layout=org.apache.log4j.PatternLayout :文件中的布局
- log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n :文件中布局的形式
log4j.properties:
### direct log messages to stdout ### log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.err log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ### direct messages to file mylog.log ### log4j.appender.file=org.apache.log4j.FileAppender log4j.appender.file.File=c\:mylog.log log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ### set log levels - for more verbose logging change 'info' to 'debug' ### log4j.rootLogger=info, stdout
log4j示例
- 在src下,复制log4j.properties
### direct log messages to stdout ### log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.err log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ### direct messages to file mylog.log ### log4j.appender.file=org.apache.log4j.FileAppender log4j.appender.file.File=c\:mylog.log log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ### set log levels - for more verbose logging change 'info' to 'debug' ### log4j.rootLogger=info, stdout
- 在cn.log4j包下,新建Log4jTest.java类
package cn.log4j; /** * 日志记录的类 */ import org.apache.log4j.Logger; import org.junit.Test; public class Log4jTest{ private Logger logger = Logger.getLogger(Log4jTest.class); @Test public void test(){ logger.fatal("致命错误"); logger.error("普通错误"); logger.warn("警告错误"); logger.info("信息"); logger.debug("调试信息"); logger.trace("堆栈信息"); } }
- 输出结果
13:58:32,908 FATAL Log4jTest:11 - 致命错误 13:58:32,910 ERROR Log4jTest:12 - 普通错误 13:58:32,910 WARN Log4jTest:13 - 警告错误 13:58:32,911 INFO Log4jTest:14 - 信息
- 设置log4j的级别为error,输出结果如下
14:02:41,650 FATAL Log4jTest:11 - 致命错误 14:02:41,652 ERROR Log4jTest:12 - 普通错误
- 设置log4j的记录器为off,输出结果如下
1.3Hibernate入门
1.3.1下载Hibernate的开发包
- http://sourceforge.net/projects/hibernate/files/hibernate3
1.3.2Hibernate框架的目录结构
- document:Hibernate的文档。
- lib:Hibernate开发的jar包。
- bytecode:操作字节码的jar包。
- jpa:Hibernate实现JPA规范的jar包。
- optional:Hibernate的可选jar包。
- required:Hibernate必须的jar包。
- project:Hibernate提供的工程
1.3.3创建一个工程(web工程)
导入相应的jar包
- hibernate3.jar
- lib/required/*.jar
- lib/jpa/hibernate-jpa-2.0-api-1.0.1.Final.jar
- 导入日志记录的jar包:
- log4j-1.2.16.jar
- slf4j-log4j12-1.7.2.jar
- 导入数据库驱动
1.3.4创建表(关系型数据库)
-- 创建数据库 create database hibernate_day01; -- 使用数据库 use hibernate_day01; -- 创建表 create table customer( id int primary key auto_increment, name ), age int );
1.3.5创建一个实体类(面向对象)
package cn.hibernate3.demo1; public class Customer { private int id; private String name; private int age; 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 int getAge() { return age; } public void setAge(int age) { this.age = age; } }
1.3.6创建ORM的映射
映射文件通常是一个XML文件就可以了,名字任意。
- 通常情况下名称规范:
- 和类在同一个包下
- 实体类名称.hbm.xml
引入约束:
- hibernate3.jar/org.hibernate.hibernate-mapping-3.0.dtd
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
- Customer.hbm.xml
<?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:类的全路径 table:表的名称 --> <class name="cn.hibernate3.demo1.Customer" table="customer"> <!-- 建立类中属性与表中字段映射--> <!-- 唯一标识,主键 --> <!-- 使用id的标签,配置唯一标识 --> <!-- 在id标签中,配置一个主键生成策略 --> <id name="id" column="id"> <!-- 主键生成策略 --> <generator class="native"/> </id> <!-- 普通属性 --> <!-- property标签:映射类中的普通属性 属性: name:类中属性的名称 column:表中字段名称 type:三种写法 java类型 :java.lang.String Hibernate类型:string SQL类型:不能直接使用type属性,需要使用子标签<column> --> <property name="name" column="name" type="java.lang.String"/> <property name="age"> <column name="age" sql-type="int"/> </property> </class> </hibernate-mapping>
1.3.7创建一个Hibernate的核心配置文件
- 通知Hibernate连接的那个数据库
- 在src下新建一个hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?> <!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> <!-- 访问数据库的url --> <property name="hibernate.connection.url"> jdbc:mysql:///hibernate_day01 </property> <!-- 用户名 --> <property name="hibernate.connection.username">root</property> <!-- 密码 --> <property name="hibernate.connection.password">root</property> <!-- 方言 --> <property name="hibernate.dialect"> org.hibernate.dialect.MySQLDialect </property> <!-- 可选配置 --> <!-- 显示SQL --> <property name="hibernate.show_sql">true</property> <!-- 格式化SQL --> <property name="hibernate.format_sql">true</property> <!-- hbm:映射 2:to ddl:create drop alter --> <property name="hibernate.hbm2ddl.auto">update</property> <!-- 通知HIbernate加载那些映射文件 --> <mapping resource="cn/hibernate3/demo1/Customer.hbm.xml" /> </session-factory> </hibernate-configuration>
1.3.8编写测试
- 新建cn.hibernate3.demo1.HIbernatetTest1类
package cn.hibernate3.demo1; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.junit.Test; /** * Hibernate入门案例的测试 */ public class HIbernatetTest1 { @Test //向数据库中插入一条记录 public void add(){ //1.HIbernate框架加载核心配置文件(有数据库连接信息)。 Configuration configuration = new Configuration().configure(); //2.创建一个SessionFactory,用户获得Session。 SessionFactory sessionFactory = configuration.buildSessionFactory(); //3.获得Session对象 Session session = sessionFactory.openSession(); //4.创建事务,默认情况下事务不提交 Transaction tx = session.beginTransaction(); //5.业务逻辑操作 Customer customer = new Customer(); customer.setName("张三"); customer.setAge(23); session.save(customer); //6.事务提交 tx.commit(); //7.释放资源,关闭Session session.close(); sessionFactory.close(); } }
1.4HIbernate的CRUD
1.4.1保存记录
@Test //向数据库中插入一条记录 public void add(){ //1.HIbernate框架加载核心配置文件(有数据库连接信息)。 Configuration configuration = new Configuration().configure(); //2.创建一个SessionFactory,用户获得Session。 SessionFactory sessionFactory = configuration.buildSessionFactory(); //3.获得Session对象 Session session = sessionFactory.openSession(); //4.创建事务,默认情况下事务不提交 Transaction tx = session.beginTransaction(); //5.业务逻辑操作 Customer customer = new Customer(); customer.setName("张三"); customer.setAge(23); session.save(customer); //6.事务提交 tx.commit(); //7.释放资源,关闭Session session.close(); sessionFactory.close(); }
1.4.2根据主键查询
- get()方法进行查询
@Test //按照id进行查询 public void demo2(){ //1.HIbernate框架加载核心配置文件(有数据库连接信息)。 Configuration configuration = new Configuration().configure(); //2.创建一个SessionFactory,用户获得Session。 SessionFactory sessionFactory = configuration.buildSessionFactory(); //3.获得Session对象 Session session = sessionFactory.openSession(); //4.创建事务,默认情况下事务不提交 Transaction tx = session.beginTransaction(); //5.业务逻辑操作 Customer customer = (Customer) session.get(Customer.class, 1); System.out.println(customer.getName()+","+customer.getAge()); //6.事务提交 tx.commit(); //7.释放资源,关闭Session session.close(); sessionFactory.close(); }
- load()方法进行查询
@Test //按照id进行查询 public void demo2(){ //1.HIbernate框架加载核心配置文件(有数据库连接信息)。 Configuration configuration = new Configuration().configure(); //2.创建一个SessionFactory,用户获得Session。 SessionFactory sessionFactory = configuration.buildSessionFactory(); //3.获得Session对象 Session session = sessionFactory.openSession(); //4.创建事务,默认情况下事务不提交 Transaction tx = session.beginTransaction(); //5.业务逻辑操作 Customer customer = (Customer) session.load(Customer.class, 1); System.out.println(customer.getName()+","+customer.getAge()); //6.事务提交 tx.commit(); //7.释放资源,关闭Session session.close(); sessionFactory.close(); }
面试题:get()和load()方法的区别?
- 1.发送SQL的时机
- load()方法采用延迟加载(懒加载),真正使用对象的数据的时候(对象的数据不包括id)。
- get()方法立即检索。当执行session.get()方法的时候,马上发送SQL语句查询。
- 2.返回的对象不同
- load()方法返回的是代理对象。
- get()方法返回的是真实对象。
- 3.查询一个不存在的数据
- load()方法抛出异常:ObjectNotFoundException。
- get()方法抛出异常:NullPointerException。
1.4.3修改记录
- 手动创建对象的方式
@Test
//修改记录 public void demo3(){ //1.HIbernate框架加载核心配置文件(有数据库连接信息)。 Configuration configuration = new Configuration().configure(); //2.创建一个SessionFactory,用户获得Session。 SessionFactory sessionFactory = configuration.buildSessionFactory(); //3.获得Session对象 Session session = sessionFactory.openSession(); //4.创建事务,默认情况下事务不提交 Transaction tx = session.beginTransaction(); //5.业务逻辑操作 Customer customer = new Customer(); customer.setId(1); customer.setName("李四"); session.update(customer); //6.事务提交 tx.commit(); //7.释放资源,关闭Session session.close(); sessionFactory.close(); }
从上面的结果来看,我并没有修改年龄,但是此时显示的是0,因为int类型的数据的默认值是0,所以实体类最好不要使用基本类型,而是使用包装类。
- 先查询再修改记录
@Test //修改记录 public void demo3(){ //1.HIbernate框架加载核心配置文件(有数据库连接信息)。 Configuration configuration = new Configuration().configure(); //2.创建一个SessionFactory,用户获得Session。 SessionFactory sessionFactory = configuration.buildSessionFactory(); //3.获得Session对象 Session session = sessionFactory.openSession(); //4.创建事务,默认情况下事务不提交 Transaction tx = session.beginTransaction(); //5.业务逻辑操作 Customer customer = (Customer) session.get(Customer.class, 1); customer.setName("李四"); session.update(customer); //6.事务提交 tx.commit(); //7.释放资源,关闭Session session.close(); sessionFactory.close(); }
此时,age的属性不为0,因为我查询出来的时候,customer对象的age就是25,所以我修改名称的时候,不会对age造成影响。
1.4.4删除记录
- 手动创建对象的方式
@Test //删除记录 public void demo4(){ //1.HIbernate框架加载核心配置文件(有数据库连接信息)。 Configuration configuration = new Configuration().configure(); //2.创建一个SessionFactory,用户获得Session。 SessionFactory sessionFactory = configuration.buildSessionFactory(); //3.获得Session对象 Session session = sessionFactory.openSession(); //4.创建事务,默认情况下事务不提交 Transaction tx = session.beginTransaction(); //5.业务逻辑操作 Customer customer = new Customer(); customer.setId(1); session.delete(customer); //6.事务提交 tx.commit(); //7.释放资源,关闭Session session.close(); sessionFactory.close(); }
- 先查询再删除记录
@Test //删除记录 public void demo4(){ //1.HIbernate框架加载核心配置文件(有数据库连接信息)。 Configuration configuration = new Configuration().configure(); //2.创建一个SessionFactory,用户获得Session。 SessionFactory sessionFactory = configuration.buildSessionFactory(); //3.获得Session对象 Session session = sessionFactory.openSession(); //4.创建事务,默认情况下事务不提交 Transaction tx = session.beginTransaction(); //5.业务逻辑操作 Customer customer = (Customer) session.get(Customer.class, 1); session.delete(customer); //6.事务提交 tx.commit(); //7.释放资源,关闭Session session.close(); sessionFactory.close(); }
1.4.5查询所有
- HQL:HIbernate Query Language
@Test //HQL public void demo5(){ //1.HIbernate框架加载核心配置文件(有数据库连接信息)。 Configuration configuration = new Configuration().configure(); //2.创建一个SessionFactory,用户获得Session。 SessionFactory sessionFactory = configuration.buildSessionFactory(); //3.获得Session对象 Session session = sessionFactory.openSession(); //4.创建事务,默认情况下事务不提交 Transaction tx = session.beginTransaction(); //5.业务逻辑操作 Query query = session.createQuery("from Customer"); List<Customer> list = query.list(); for (Customer customer : list) { System.out.println(customer.getName()+","+customer.getAge()); } //6.事务提交 tx.commit(); //7.释放资源,关闭Session session.close(); sessionFactory.close(); }
- QBC:Query By Criteria
@Test //QBC public void demo5(){ //1.HIbernate框架加载核心配置文件(有数据库连接信息)。 Configuration configuration = new Configuration().configure(); //2.创建一个SessionFactory,用户获得Session。 SessionFactory sessionFactory = configuration.buildSessionFactory(); //3.获得Session对象 Session session = sessionFactory.openSession(); //4.创建事务,默认情况下事务不提交 Transaction tx = session.beginTransaction(); //5.业务逻辑操作 Criteria criteria = session.createCriteria(Customer.class); List<Customer> list = criteria.list(); for (Customer customer : list) { System.out.println(customer.getName()+","+customer.getAge()); } //6.事务提交 tx.commit(); //7.释放资源,关闭Session session.close(); sessionFactory.close(); }
- SQL
@Test //SQL public void demo5(){ //1.HIbernate框架加载核心配置文件(有数据库连接信息)。 Configuration configuration = new Configuration().configure(); //2.创建一个SessionFactory,用户获得Session。 SessionFactory sessionFactory = configuration.buildSessionFactory(); //3.获得Session对象 Session session = sessionFactory.openSession(); //4.创建事务,默认情况下事务不提交 Transaction tx = session.beginTransaction(); //5.业务逻辑操作 Query query = session.createSQLQuery("select * from customer"); List<Object[]> list = query.list(); for (Object[] obj : list) { System.out.println(Arrays.toString(obj)); } //6.事务提交 tx.commit(); //7.释放资源,关闭Session session.close(); sessionFactory.close(); }
@Test //SQL public void demo5(){ //1.HIbernate框架加载核心配置文件(有数据库连接信息)。 Configuration configuration = new Configuration().configure(); //2.创建一个SessionFactory,用户获得Session。 SessionFactory sessionFactory = configuration.buildSessionFactory(); //3.获得Session对象 Session session = sessionFactory.openSession(); //4.创建事务,默认情况下事务不提交 Transaction tx = session.beginTransaction(); //5.业务逻辑操作 Query query = session.createSQLQuery("select * from customer").addEntity(Customer.class); List<Customer> list = query.list(); for (Customer customer : list) { System.out.println(customer.getName()+","+customer.getAge()); } //6.事务提交 tx.commit(); //7.释放资源,关闭Session session.close(); sessionFactory.close(); }
1.5Hibernate的常用配置
Hibernate的持久层方案,将用户从原始的JDBC底层的SQL访问中解放出来。
用户无需关注底层数据库操作,只要通过操作映射到数据表的java对象,就可以对数据库进行增删改查。
Hibernate框架支持两种Hibernate属性配置方式
- hibernate.properties:采用properties方式,必须手动编程加载hbm文件或者持久化类。
- hibernate.cfg.xml:采用xml配置方式,可以配置添加hbm文件。
1.5.1Hibernate的常见配置之hibernate.cfg.xml
- 必须的配置
- 连接数据库的4个基本参数:
- hibernate.connection.driver_class 连接数据库驱动程序
- hibernate.connection.url 连接数据库URL
- hibernate.connection.username 数据库用户名
- hibernate.connection.password 数据库密码
- Hibernate的方言:
- hibernate.dialect 操作数据库方言
- 连接数据库的4个基本参数:
- 可选的配置
- hibernate.show_sql true 在控制台上输出SQL语句
- hibernate.format_sql true 格式化控制台输出的SQL语句
hibernate.connection.autocommit true 事务是否自动提交
hibernate.hbm2ddl.auto create/create-drop/update/validate
- create :每次执行的时候,创建一个新的表.(如果以前有该表,将该表删除重新创建.) 一般测试的时候的使用.
- create-drop :每次执行的时候,创建一个新的表,程序执行结束后将这个表,删除掉了. 一般测试的时候使用.
- update :如果数据库中没有表,创建一个新的表,如果有了,直接使用这个表.可以更新表的结构.
- validate :会使用原有的表.完成校验.校验映射文件与表中配置的字段是否一致.不一致报错.
- 映射的配置
- 在核心配置文件中加载映射文件:
- <mapping resource="cn/hibernate3/demo1/Customer.hbm.xml" />
- 使用手动编码的方式进行加载。
- 在核心配置文件中加载映射文件:
1.5.2Hibernate的常见配置之对象.mapper.xml
ORM:对象和关系的映射
- 配置java对象与表映射。
- 配置类与表的映射:
- name:类的全路径。
- table:表的名称(可以省略的,使用类的名称作为表名)。
- <class name="cn.hibernate3.demo1.Customer" table="customer"></class>
- 配置类与表的映射:
- 配置普通属性与字段映射
- <property name="name" column="name" type="java.lang.String"/>
- type:三种写法
- java类型:java.lang.String
- Hibernate类型:string
- SQL类型:不能直接使用type属性,需要使用子标签<column>
- <column name="name" sql-type="varchar(20)"/>
- 配置唯一标识与主键映射:
- 一个表中只有一个主键的形式:
<id name="id" column="id"> <!-- 主键生成策略 --> <generator class="native"/> </id>
- 一个表对应多个主键的形式(复合主键):
- <composite-id ></composite-id>
- 一个表对应多个主键的形式(复合主键):
- 关联关系
- 预定义SQL(命名式SQL)
<query name="findAll"> from Customer </query>
@Test public void demo6(){ //1.HIbernate框架加载核心配置文件(有数据库连接信息)。 Configuration configuration = new Configuration().configure(); //2.创建一个SessionFactory,用户获得Session。 SessionFactory sessionFactory = configuration.buildSessionFactory(); //3.获得Session对象 Session session = sessionFactory.openSession(); //4.创建事务,默认情况下事务不提交 Transaction tx = session.beginTransaction(); //5.业务逻辑操作 Query query = session.getNamedQuery("findAll"); List<Object> list = query.list(); for (Object object : list) { Customer customer = (Customer)object; System.out.println(customer.getName()+","+customer.getAge()); } //6.事务提交 tx.commit(); //7.释放资源,关闭Session session.close(); sessionFactory.close(); }
1.6Hibernate的核心API
1.6.1Configuration类
加载核心配置文件:
- hibernate.cfg.xml:
- 加载
- Configuration configuration = new Configuration().configure();
- hibernate.properties
- 加载
- Configuration configuration = new Configuration();
加载映射文件:
- 第一种写法
configuration.addResource("cn/itcast/hibernate3/demo1/Customer.hbm.xml");
- 第二种写法(要求:映射文件名称要规范,类与映射在同一个包下)
configuration.addClass(Customer.class);
1.6.2SessionFactory接口--Session的工厂
- Configuration对象根据当前的配置信息生成SessionFactory对象。
- SessionFactory对象中保存了当前的数据库配置信息和所有映射关系以及预定义的SQL语句。
- SessionFactory对象是线程安全的。
- SessionFactory还负责维护Hibernate的二级缓存。
//1.HIbernate框架加载核心配置文件(有数据库连接信息)。 Configuration configuration = new Configuration().configure(); //2.创建一个SessionFactory,用户获得Session。 SessionFactory sessionFactory = configuration.buildSessionFactory();
- 可以通过SessionFactory对象获取Session对象
//3.获得Session对象 Session session = sessionFactory.openSession();
【注意】构造SessionFactory很消耗资源,一般情况下,一个应用只初始化一次。
抽取代码,形成一个工具类HibernateUtils.java类
package cn.utils; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; /** * Hibernate抽取工具类 */ public class HibernateUtils { private static Configuration configuration; private static SessionFactory sessionFactory; static{ configuration = new Configuration().configure(); sessionFactory = configuration.buildSessionFactory(); } public static Session openSession(){ return sessionFactory.openSession(); } }
在Hibernate中配置c3p0
- 引入c3p0的jar包。
- 在核心配置hibernate.cfg.xml文件中配置
<!-- C3P0连接池设定--> <!-- 使用c3po连接池 配置连接池提供的供应商--> <property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property> <!--在连接池中可用的数据库连接的最少数目 --> <property name="c3p0.min_size">5</property> <!--在连接池中所有数据库连接的最大数目 --> <property name="c3p0.max_size">20</property> <!--设定数据库连接的过期时间,以秒为单位, 如果连接池中的某个数据库连接处于空闲状态的时间超过了timeout时间,就会从连接池中清除 --> <property name="c3p0.timeout">120</property> <!--每3000秒检查所有连接池中的空闲连接 以秒为单位--> <property name="c3p0.idle_test_period">3000</property>
1.6.3Session接口
- 相当于jdbc中的Connection。
- Session是应用程序与数据库之间交互操作的一个单线程对象,是Hibernate运作的中心。
- Session是线程不安全的。
- 所有持久化对象必须在Session的管理下才可以进行持久化操作。
- Session对象有一个一级缓存,显示执行flush之前,所有的持久化操作数据都将缓存在Session对象处。
- 持久化类与Session关联起来后就具有了持久化的能力。
- 常用方法:
- save()/persist() 添加
- update() 修改
- saveOrUpdate() 添加或修改对象
- delete() 删除对象
- get()/load() 根据主键查询
- createQuery() 创建一个Query接口,编写HQL语句。
- createSQLQuery() 创建一个SQLQuery接口,编写SQL语句操作数据库。
- createCriteria() 返回一个Criteria接口,条件查询。
1.6.4Transaction接口
- 代表数据库操作的事务对象
Transaction tx = session.beginTransaction();
- 提供事务管理的方法
- commit() 提交相关联的Session实例。
- rollback() 撤销事务操作
- wasCommitted() 检查事务是否提交
1.6.5Query接口
- Query代表面向对象的一个Hibernate查询操作。
- sesson.createQuery(String hql)接收一个HQL语句。
- HQL是Hibernate Query Language缩写,语法很像SQL语法,但是完全面向对象。
- 使用HQL对象的步骤:
- 获取Hibernate的Sessioin对象。
- 编写HQL语句。
- 调用session.createQuery(String hql),创建查询对象。
- 如果HQL语句中包含参数,则调用Query的setXXX设置参数。
- 调用Query对象的list()或uniqueResult()方法执行查询
- Query还包含两个方法,用于控制返回结果
- setFirstResult(int firstResult) 设置返回结果从第几条开始
- setMaxResult(int maxResult) 设置本次返回结果记录条数
- HQL入门举例
- 以from开始HQL语句,调用list()方法返回List<Customer>。
- from Customer 查询customer表所有数据。
- 使用select关键字(查询部门对象属性)
- select name from Customer 返回List<String>
- select name,age from Customer 返回List<Object[]>
- select c.name from Customer as c 为Customer实例起别名
- 使用where添加条件
- from Customer as c where c.age >:age,其中age是参数
- List<Customer> list = session.createQuery("from Customer where age >:age").setParameter("age", 2).list();
- from Customer as c wher c.age > ?,其中?是参数
- List<Customer> list = session.createQuery("from Customer where name = ?").setString(0, "bb").list();
- from Customer as c where c.age >:age,其中age是参数
- 以from开始HQL语句,调用list()方法返回List<Customer>。
@Test //HQL public void demo7(){ //1.HIbernate框架加载核心配置文件(有数据库连接信息)。 Configuration configuration = new Configuration().configure(); //2.创建一个SessionFactory,用户获得Session。 SessionFactory sessionFactory = configuration.buildSessionFactory(); //3.获得Session对象 Session session = sessionFactory.openSession(); //4.创建事务,默认情况下事务不提交 Transaction tx = session.beginTransaction(); //5.业务逻辑操作 List<Customer> list = session.createQuery("from Customer").list(); for (Customer customer : list) { System.out.println(customer.getName()+","+customer.getAge()); } //6.事务提交 tx.commit(); //7.释放资源,关闭Session session.close(); sessionFactory.close(); }
@Test //HQL public void demo7(){ //1.HIbernate框架加载核心配置文件(有数据库连接信息)。 Configuration configuration = new Configuration().configure(); //2.创建一个SessionFactory,用户获得Session。 SessionFactory sessionFactory = configuration.buildSessionFactory(); //3.获得Session对象 Session session = sessionFactory.openSession(); //4.创建事务,默认情况下事务不提交 Transaction tx = session.beginTransaction(); //5.业务逻辑操作 List<Customer> list = session.createQuery("from Customer where name = ?").setString(0, "bb").list(); for (Customer customer : list) { System.out.println(customer.getName()+","+customer.getAge()); } //6.事务提交 tx.commit(); //7.释放资源,关闭Session session.close(); sessionFactory.close(); }
@Test //HQL public void demo7(){ //1.HIbernate框架加载核心配置文件(有数据库连接信息)。 Configuration configuration = new Configuration().configure(); //2.创建一个SessionFactory,用户获得Session。 SessionFactory sessionFactory = configuration.buildSessionFactory(); //3.获得Session对象 Session session = sessionFactory.openSession(); //4.创建事务,默认情况下事务不提交 Transaction tx = session.beginTransaction(); //5.业务逻辑操作 List<Customer> list = session.createQuery("from Customer").setFirstResult(0).setMaxResults(2).list(); for (Customer customer : list) { System.out.println(customer.getName()+","+customer.getAge()); } //6.事务提交 tx.commit(); //7.释放资源,关闭Session session.close(); sessionFactory.close(); }
1.6.6Criteria接口
- Criteria是Hibernate提供的用于条件查询接口。
- Criteria criteria = session.createCriteria(Customer.class);
- 使用Criteria对象步骤:
- 获取Hibernate的Session对象。
- 通过Session获取Criteria对象。
- 通过restrictions的静态方法创建Criterion条件对象
- 向Criteria对象中添加Criterion 查询条件。
- 执行Criteria的list()或uniqueResult()获取结果。
@Test //QBC public void demo8(){ //1.HIbernate框架加载核心配置文件(有数据库连接信息)。 Configuration configuration = new Configuration().configure(); //2.创建一个SessionFactory,用户获得Session。 SessionFactory sessionFactory = configuration.buildSessionFactory(); //3.获得Session对象 Session session = sessionFactory.openSession(); //4.创建事务,默认情况下事务不提交 Transaction tx = session.beginTransaction(); //5.业务逻辑操作 List<Customer> list = session.createCriteria(Customer.class).list(); for (Customer customer : list) { System.out.println(customer.getName()+","+customer.getAge()); } //6.事务提交 tx.commit(); //7.释放资源,关闭Session session.close(); sessionFactory.close(); }
@Test //QBC public void demo8(){ //1.HIbernate框架加载核心配置文件(有数据库连接信息)。 Configuration configuration = new Configuration().configure(); //2.创建一个SessionFactory,用户获得Session。 SessionFactory sessionFactory = configuration.buildSessionFactory(); //3.获得Session对象 Session session = sessionFactory.openSession(); //4.创建事务,默认情况下事务不提交 Transaction tx = session.beginTransaction(); //5.业务逻辑操作 List<Customer> list = session.createCriteria(Customer.class).add(Restrictions.eq("name", "bb")).list(); for (Customer customer : list) { System.out.println(customer.getName()+","+customer.getAge()); } //6.事务提交 tx.commit(); //7.释放资源,关闭Session session.close(); sessionFactory.close(); }
@Test //QBC public void demo8(){ //1.HIbernate框架加载核心配置文件(有数据库连接信息)。 Configuration configuration = new Configuration().configure(); //2.创建一个SessionFactory,用户获得Session。 SessionFactory sessionFactory = configuration.buildSessionFactory(); //3.获得Session对象 Session session = sessionFactory.openSession(); //4.创建事务,默认情况下事务不提交 Transaction tx = session.beginTransaction(); //5.业务逻辑操作 List<Customer> list = session.createCriteria(Customer.class).setFirstResult(0).setMaxResults(2).list(); for (Customer customer : list) { System.out.println(customer.getName()+","+customer.getAge()); } //6.事务提交 tx.commit(); //7.释放资源,关闭Session session.close(); sessionFactory.close(); }
1.7Hibernate中的持久化类
Hibernate中采用普通、传统的java对象(POJO),作为持久化类,与数据库进行映射。换句话说,持久化类:实体类+映射文件。
持久化类的编写规则:
- 提供一个无参数public访问控制的构造器 :用于反射。
- 提供一个标识属性(唯一标识,OID),映射数据表主键字段
- java区分两个对象是否是同一个,使用地址来进行区分。
- 数据库区分两条记录是否一致,使用主键来进行区分。
- Hibernate中区分持久化对象是否是同一个,根据唯一标识。
- 所有属性提供public访问控制符的setter和getter方法 :框架中存值和取值的时候使用。
- 标识属性应尽量使用基本数据类型的包装类型
- 使用基本数据类型
学号 | 姓名 | 成绩 |
1 | 张三 | 0 |
- 使用包装类型
学号 | 姓名 | 成绩 |
1 | 张三 | null |
- 持久化类不要使用final进行修饰
- 用final修饰的类不能被继承,无法生成代理对象(延迟加载的时候返回代理对象,延迟加载失效)。
示例:演示Hibernate是通过唯一标识来区分持久化类的。
@Test public void demo9(){ //1.HIbernate框架加载核心配置文件(有数据库连接信息)。 Configuration configuration = new Configuration().configure(); //2.创建一个SessionFactory,用户获得Session。 SessionFactory sessionFactory = configuration.buildSessionFactory(); //3.获得Session对象 Session session = sessionFactory.openSession(); //4.创建事务,默认情况下事务不提交 Transaction tx = session.beginTransaction(); //5.业务逻辑操作
//先查询id为1的客户 Customer customer = (Customer) session.get(Customer.class, 1);
//新建一个id为1的客户 Customer customer2 = new Customer(); customer2.setId(1); customer2.setName("hehe"); //更新cutomer2对象 session.update(customer2); //6.事务提交 tx.commit(); //7.释放资源,关闭Session session.close(); sessionFactory.close(); }
区分自然主键和代理主键
- 在关系型数据库表中,用主键来识别记录并保证每条记录的唯一性。作为主键的字段必须满足以下条件:
- 不允许为null。
- 每条记录具有唯一的主键值,不允许主键值重复。
- 每条记录的主键值永远不会改变。
- 在customer表中,如果把name字段作为主键,前提条件是:
- 每条记录的客户姓名不允许为null。
- 不允许客户重名。
- 不允许修改客户姓名。
- name字段是具有业务含义的字段,把这种字段作为主键,称为自然主键。尽管也是可行的,但是不能满足不断变化的业务需求,一旦出现了允许客户重名的业务需求,就必须修改数据类型,重新定义表的主键,这给数据库的维护增加了难度。
- 因此,更合理的方式是使用代理主键,即不具备业务含义的字段,该字段一般取名为“ID”,代理主键通常为整数类型,因为整数类型比字符串类型要节省更多的数据库空间。那么代理主键的值从何而来呢?许多数据库都提供了自动生成代理主键的机制。
- 在Hibernate中尽量要Hibernate自己去维护主键:
- 主键生成策略。
1.8主键生成策略
- increment:自动增长,适合short、int、long等,不是使用数据库的自动增长机制,而是使用Hibernate框架提供的自动增长方式。
- select max(id) from 表;在最大值的基础上+1,(多线程问题),在集群下不要使用。
- identity:自动增长,适合short、int、long等,采用数据库的自动增长机制。不适合Oracle数据库。
- sequence:序列,适合short、int、long等,应用在Oracle上。
- uuid:适合于字符串类型的主键,采用随机的字符串作为主键。
- native:本地策略,底层数据库不同,自动选择使用identity还是sequence。
- assigned:Hibernate框架不维护主键,主键由程序自动生成。
- foreign:主键是外来的。(应用在多表的一对一的关系上)。
1.9映射复合主键
package cn.hibernate3.demo2; import java.io.Serializable; public class Customer implements Serializable{ private String firstName; private String lastName; private String desc; public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } }
<?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:类的全路径 table:表的名称 --> <class name="cn.hibernate3.demo1.Customer" table="customer"> <!-- 建立类中属性与表中字段映射--> <!-- 唯一标识,主键 --> <!-- 使用id的标签,配置唯一标识 --> <!-- 在id标签中,配置一个主键生成策略 --> <composite-id> <key-property name="firstName" column="firstName" type="string"/> <key-property name="lastName" column="lastName" type="string"/> </composite-id> <!-- 普通属性 --> <!-- property标签:映射类中的普通属性 属性: name:类中属性的名称 column:表中字段名称 type:三种写法 java类型 :java.lang.String Hibernate类型:string SQL类型:不能直接使用type属性,需要使用子标签<column> --> <property name="desc" column="desc" type="java.lang.String"/> </class> </hibernate-mapping>
@Test //向数据库中插入一条记录 public void demo1(){ //1.HIbernate框架加载核心配置文件(有数据库连接信息)。 Configuration configuration = new Configuration().configure(); //2.创建一个SessionFactory,用户获得Session。 SessionFactory sessionFactory = configuration.buildSessionFactory(); //3.获得Session对象 Session session = sessionFactory.openSession(); //4.创建事务,默认情况下事务不提交 Transaction tx = session.beginTransaction(); //5.业务逻辑操作 Customer customer = new Customer(); customer.setFirstName("张"); customer.setLastName("三丰"); session.save(customer); //6.事务提交 tx.commit(); //7.释放资源,关闭Session session.close(); sessionFactory.close(); }
Hibernate(一)的更多相关文章
- hibernate多对多关联映射
关联是类(类的实例)之间的关系,表示有意义和值得关注的连接. 本系列将介绍Hibernate中主要的几种关联映射 Hibernate一对一主键单向关联Hibernate一对一主键双向关联Hiberna ...
- 解决 Springboot Unable to build Hibernate SessionFactory @Column命名不起作用
问题: Springboot启动报错: Caused by: org.springframework.beans.factory.BeanCreationException: Error creati ...
- hibernate多对一双向关联
关联是类(类的实例)之间的关系,表示有意义和值得关注的连接. 本系列将介绍Hibernate中主要的几种关联映射 Hibernate一对一主键单向关联Hibernate一对一主键双向关联Hiberna ...
- Hibernate中事务的隔离级别设置
Hibernate中事务的隔离级别,如下方法分别为1/2/4/8. 在Hibernate配置文件中设置,设置代码如下
- Hibernate中事务声明
Hibernate中JDBC事务声明,在Hibernate配置文件中加入如下代码,不做声明Hibernate默认就是JDBC事务. 一个JDBC 不能跨越多个数据库. Hibernate中JTA事务声 ...
- spring applicationContext.xml和hibernate.cfg.xml设置
applicationContext.xml配置 <?xml version="1.0" encoding="UTF-8"?> <beans ...
- [原创]关于Hibernate中的级联操作以及懒加载
Hibernate: 级联操作 一.简单的介绍 cascade和inverse (Employee – Department) Casade用来说明当对主对象进行某种操作时是否对其关联的从对象也作类似 ...
- hibernate的基本xml文件配置
需要导入基本的包hibernate下的bin下的required和同bin下optional里的c3p0包下的所有jar文件,当然要导入mysql的驱动包了.下面需要注意的是hibernate的版本就 ...
- Maven搭建SpringMVC+Hibernate项目详解 【转】
前言 今天复习一下SpringMVC+Hibernate的搭建,本来想着将Spring-Security权限控制框架也映入其中的,但是发现内容太多了,Spring-Security的就留在下一篇吧,这 ...
- 1.Hibernate简介
1.框架简介: 定义:基于java语言开发的一套ORM框架: 优点:a.方便开发; b.大大减少代码量; c.性能稍高(不能与数据库高手相比,较一般数据库使用者 ...
随机推荐
- 基于vue2.0的网易云音乐 (实时更新)
本人在自学vue,之后想在学习过程中加以实践.由于之前有做过jquery的播放器效果,ui仿照网易云,地址 www.daiwei.org/music 于是就想做vue 的网易云播放器,网上也有类似的项 ...
- dynamic-load-apk 插件与宿主方法互调
新建项目 DlPluginHost,下载dynamic-load-apk源码 1.将dynamic-load-apk 文件夹中的lib做为module导入到DlPlginHost 2.导入到Plugi ...
- (转载)KMP算法讲解
网上找到了一篇详细讲解KMP字符串匹配算法,质量很高.特备忘于此. 摘自:http://blog.csdn.net/v_july_v/article/details/7041827 实现代码如下: / ...
- iconfont字体图标的使用方法--超简单!
我之前因为项目用bootstrap比较多,所以使用font awesome字体图标比较多,后来接触到了iconfont,发现想要的什么图标都有,还可以自定义图标,非常强大!之前看了一波教程,觉得繁琐, ...
- Maven-FAQ
1.Failure to transfer org.apache.maven.plugins:maven-resources-plugin:pom:2.5...: Q: 第一次使用maven+ecli ...
- linux DNS 问题
今天准备爬虫51job时候,发现ping不通外网了,ping 了一下IP,都是OK的,只是host不通. 呵呵,就一DNS问题,好的.第一步,开始检查配置文件 cat /etc/sysconfig/n ...
- 小型 Web 页项目打包优化方案
背景 目前团队中新的 Web 项目基本都采用了 Vue 或 React ,加上 RN,这些都属于比较重量级的框架,然而对于小型 Web 页面,又显得过大.早期的一些项目则使用了较原始的 HTML ...
- vue2中component父子组件传递数据props的使用
子组件使用父亲传过来的数据,我们需要通过子组件的 props 选项. 组件实例的作用域是孤立的,不能在子组件的模板内直接引用父组件的数据.修改父亲传过来的props数据的时候 父亲必须传递对象,否则不 ...
- (转)Spring Boot Junit单元测试
场景:在项目开发中要测试springboot工程中一个几个dao和service的功能是否正常,初期是在web工程中进行要素的录入,工作量太大.使用该单元测试大大减小了工作强度. Junit这种老技术 ...
- 走进STM32世界之Hex程序烧写
多数51单片机(STC系列单片机)的初学者都知道,在51单片机初上电时,可以通过PC机上位机软件将程序引导至bootloader,从而将新程序的hex文件下载至单片机中,完成程序的升级或是更新.在32 ...