hibernate(一)helloworld、api、事务、配置文件、映射文件
hibernate 系列
hibernate(一)helloworld、api、事务、配置文件、映射文件
hibernate(二)对象的三种状态、一级缓存、多对一、inverse、cascade
hibernate(三)多对多、加载策略、懒加载、HQL查询、整合c3p0、乐观锁悲观锁
hibernate(四)整合log4j、一对一、二级缓存
1、hibernate 介绍
2、ORM 介绍
3、Java 种常用的 ORM 技术
4、hibernate hello world 程序
5、Hibernate-api详解
5.1、Configuration对象
5.2、SessionFactory对象
5.3、Session-增删改
5.4、Session-HQL查询
5.5、Session-Criteria&Sql查询
5.6、session.load()
5.7、Transaction详解
5.8、Query详解
5.9、Criteria详解(了解,开发中用得不多)
5.10、封装Hibernate工具类
6、Hibernate-配置文件
7、Hibernate-实体配置详解-实体规则
8、映射文件详解
1、hibernate 介绍 <--返回目录
hibernate 在 javaEE 三层架构的位置
2、ORM 介绍 <--返回目录
ORM:对象关系映射(Object Relational Mapping,简称ORM)是通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中。本质上就是将数据从一种形式转换到另外一种形式。
对象 Object:java 对象,此处特指 JavaBean
关系 Relational:二维表,数据库的表
映射 Mapping:对象的属性 与表字段 存在对应关系
3、Java 种常用的 ORM 技术 <--返回目录
1)JPA(Java Persistence API):JPA 通过 JDK5 注解或 XML 描述对象-关系表的映射关系(只有接口规范)
2)Hibernate:ORM 框架,通过对象-关系映射配置,可以完全脱离底层 sql
3)mybatis:apache 开源项目 ibatis,支持普通 sql 查询,存储过程和高级映射的优秀持久层框架
4)apache DBUtils、Spring JDBCTemplate
4、hibernate hello world 程序 <--返回目录
demo 最终结构
新建一个 Java Project
依赖
链接:https://pan.baidu.com/s/12nwIyodOhVCEemaAyPVPtQ 提取码:tp9w
依赖 Add to Build Path
创建实体类
public class User { private Integer id; private String username; private String password; //getter和setter省略 }
mysql 创建表
CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(100) DEFAULT NULL, `password` varchar(100) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
hibernate 配置文件 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> <!-- 连接数据库的地址 --> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8</property> <!-- 连接数据库的用户名 --> <property name="hibernate.connection.username">root</property> <!-- 连接数据库的密码 --> <property name="hibernate.connection.password">123456</property> <!-- show_sql: 操作数据库时, 会向控制台打印 sql 语句 --> <property name="show_sql">true</property> <!-- format_sql: 打印 sql 语句前, 会先将 sql 语句格式化 --> <property name="format_sql">true</property> <!-- hbm2ddl.auto: 生成表结构的策略配置。 update(最常用):如果当前数据库中不存在表结构,那么自动创建表结构。如果存在表结构,并且表结构与实体一致, 那么不做修改。如果存在表结构,并且表结构与实体不一致,那么会修改表结构,会保留原有列。 create(很少用):无论是否存在表结构,每次启动 Hibernate 都会重新创建表结构(数据会丢失) 。 create-drop(极少用):无论是否存在表结构,每次启动 Hibernate 都会重新创建表结构。 每次 Hibernate 运行结束时,删除表结构。 validate(很少用):不会自动创建表结构,也不会自动维护表结构。Hibernate只校验表结构。 如果表结构不一致将会抛出异常。 --> <property name="hbm2ddl.auto">update</property> <!-- 数据库方言配置 org.hibernate.dialect.MySQLDialect (选择最短的) --> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <!-- hibernate.connection.autocommit: 事务自动提交,默认false --> <property name="hibernate.connection.autocommit">true</property> <!-- 引入ORM 映射文件 填写src之后的路径 --> <mapping resource="com/oy/helloworld/User.hbm.xml" /> </session-factory> </hibernate-configuration>
映射文件 User.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"> <!-- ORM元数据 表对象关系映射文件 package: 配置该配置文件 实体类 所在的包 --> <hibernate-mapping package="com.oy.helloworld"> <!--class: 配置实体与表的关系 name : 填写实体的完整类名 table: 与实体对应表的名称 dynamic-insert:动态插入,默认值是false true => 如果字段值为null,不参与 insert 语句 dynamic-update:动态更新,默认值"false" true => 没改动过的属性,将不会生成到 update 语句中 --> <class name="User" table="user"> <!--id: 配置实体与表中 id对应 name: user对象中标识主键的属性名称 column: 主键在表中的列名 length: 列的数据长度 unsaved-value(不常用): 指定主键为什么值时,当做null来处理. access(强烈推荐不要用): field 那么在操作属性时,会直接操作对应的字段而不是get/set方法 --> <id name="id" column="id" length="100"> <!-- generator:主键生成策略 1.increment 数据库自己生成主键. 先从数据库中查询最大的ID值,将ID值加1作为新的主键 2.identity 依赖于数据的主键自增功能 3.sequence 序列,依赖于数据中的序列功能(Oracle). 4.hilo(了解) : Hibernate自己实现序列的算法,自己生成主键. (hilo算法 ) 5.native 自动根据数据库判断,三选一. identity|sequence|hilo 6.uuid 生成32位的不重复随机字符串当做主键 7.assigned 自己指定主键值. 表的主键是自然主键时使用。--> <generator class="identity"></generator> </id> <!-- property : 实体中属性与表中列的对应 name : 实体中属性名称 column : 表中列的名称 length : 数据长度 precision: 小数点后的精度 scale: 有效位数 insert(一般不用): 该属性是否加入insert语句. update(一般不用): 该属性是否加入update语句. not-null : 指定属性的约束是否使用 非空 unique : 指定属性的约束是否使用 唯一 --> <!-- type: 表达该属性的类型 可以用三种方式指定属性 java类型 数据库类型指定 Hibernate类型指定 java.lang.String varchar string --> <property name="username" column="username" update="true" type="string" ></property> <property name="password" column="password"></property> <!-- <property name="sal" column="sal" precision="2" scale="3" ></property> --> </class> </hibernate-mapping>
测试类
package com.oy.helloworld; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import org.junit.Test; public class TestHelloWorld { @Test public void fun1() { // 读取配置文件 Configuration conf = new Configuration().configure(); // 根据配置 创建Factory SessionFactory sessionFactory = conf.buildSessionFactory(); // 通过获得操作数据库的session对象 Session session = sessionFactory.openSession(); // 操作数据库 User u = new User(); u.setUsername("tom"); u.setPassword("222"); session.save(u); // 关闭资源 session.close(); sessionFactory.close(); } }
测试结果:控制台打印
Hibernate:
insert
into
user
(username, password)
values
(?, ?)
数据库记录插入成功
需要注意的地方:
1)hibernate 默认需要手动开启提交事务,也可以配置自动提交事务
<!-- hibernate.connection.autocommit: 事务自动提交,默认false --> <property name="hibernate.connection.autocommit">true</property>
2)mysql 引擎 MyISAM 不支持事务,所以如果使用 MyISAM 引擎,事务失效,插入总是成功(不会回滚),也即
<property name="hibernate.connection.autocommit">false</property> 配置成 false,也会插入成功。
测试 事务
<property name="hibernate.connection.autocommit">false</property>
hibernate.connection.autocommit 配置成 false,事务不会自动提交,插入记录被回滚了
5、Hibernate-api详解 <--返回目录
5.1、Configuration对象 <--返回目录
加载src下名为hibernate.cfg.xml
Configuration conf = new Configuration().configure();
如果配置文件不符合默认加载规则,调用
Configuration conf = new Configuration().configure(File file);//通过file加载 Configuration conf = new Configuration().configure(String path);//通过路径加载
可以通过Configuration对象加载映射文件(不推荐)。conf.addClass(User.class);之所以可以这样实现加载,因为有下面规范
规范1:ORM映射文件名称与实体名称一致;
规范2:ORM映射文件需要与实体类放在同一包下
推荐使用hibernate.cfg.xml 使用mapping属性引入映射文件
<mapping resource="com/oy/domain/User.hbm.xml"/>
5.2、SessionFactory对象 <--返回目录
创建 Factory
Configuration conf = new Configuration().configure(); // 读取配置文件 SessionFactory sessionFactory = conf.buildSessionFactory();
获取一个全新的 session 对象
Session session = sessionFactory.openSession();
获得与当前线程绑定的 session 对象,如果没有,获取一个新的 session
先配置:<property name="hibernate.current_session_context_class">thread</property>
将session与线程绑定,只有配置了该参数,才能使用getCurrentSession()
Session session = sessionFactory.getCurrentSession();
5.3、Session-增删改 <--返回目录
增
User user = new User(); user.setUname("李四"); user.setPassword("123"); session.save(user);
改
//先查 //开启事务 Transaction ts= session.beginTransaction(); //查 User _user = (User) session.get(User.class, 1);//取一个User对象,id=1 System.out.println(_user); //改 _user.setPassword("abc"); //修改密码 _user.setUname("张三"); //修改密码 session.update(_user); //执行修改 //关闭事务 ts.commit();
或者
User user1 = new User(); user1.setUid(1); //指定id user1.setPassword("def"); //修改密码 user1.setUname("zhangsan"); //修改用户名 Transaction ts= session.beginTransaction(); //修改操作必须先开启事务 session.update(user1); //执行修改 ts.commit(); //提交事务
删(根据id删除,只有对象有id就行)
//User _user = (User) session.get(User.class, 1);//取一个User对象,id=1 User user2 = new User(); user2.setUid(1); //指定id Transaction ts= session.beginTransaction(); //删除操作必须先开启事务 session.delete(user2); ts.commit(); //提交事务
5.4、Session-HQL查询 <--返回目录
HQL语言:Hibernate Query Language
session.createQuery("HQL语句");
查询所有
Query query = session.createQuery("from com.oy.domain.User");
List<User> userList = query.list();//list()将语句执行,并返回结果
5.5、Session-Criteria&Sql查询 <--返回目录
Criteria查询==>Hibernate独创的面向对象的查询==>无语句
//查询所有 Criteria criteria = session.createCriteria(User.class); List<User> userList = criteria.list();
原生的sql查询,查询所有
SQLQuery query = session.createSQLQuery("select * from t_user "); query.addEntity(User.class); List<User> userList = query.list();
5.6、session.load() <--返回目录
问题1:load()方法,返回一个代理对象,获得其内容时,会查询数据库,是每次访问属性都会查询数据库吗?
答:不是每次都查。代理对象中有一个表识是否被初始化的boolean型变量,记录是否被初始化过。
问题2:代理都是要基于接口的,用load()方法返回的代理,就没有实现任何接口?
答:java中的动态代理是基于接口;而Hibernate是使用javassist-3.12.0.GA.jar产生代理对象,
该代理与被代理对象之间的关系是继承关系。代理对象是被代理对象的子类。
5.7、Transaction详解 <--返回目录
* 开启事务 Transaction ts= session.beginTransaction();
* 提交事务 ts.commit();
回滚事务 ts.rollback();
* 获得已经打开的事务对象(很少用)
session.getTransaction();
* 事务关闭时,会自动把与当前线程关联的session关闭,并删除
事务代码规范写法
Session session = null; Transaction tx = null; try { session = HibernateUtils.openSession(); tx = session.beginTransaction(); // 开启事务 // ============================================== // ============================================== tx.commit(); // 提交事务 } catch (Exception e) { tx.rollback(); // 回滚事务 } finally { session.close(); // 关闭操作 }
5.8、Query详解 <--返回目录
* Query对象:封装HQL语句的对象
* 查询所有
Query query = session.createQuery("from com.oy.domain.User");
List<User> userList = query.list();//list()方法将hql句执行,并返回List<User>
* 查询一条记录
Query query = session.createQuery("from com.oy.domain.User where uname='张三'");
User u = (User)query.uniqueResult();//执行hql语句,返回一个User对象
* 分页 limit Index,count;
query.setFirstResult(index);//指定结果从第index个取
query.setMaxResults(count);//指定取几条记录
5.9、Criteria详解(了解,开发中用得不多) <--返回目录
* Criteria查询==>Hibernate独创的面向对象的查询==>无语句
* 查询所有
Criteria criteria = session.createCriteria(User.class);
List<User> userList = criteria.list();
* 查询一条记录
Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.eq("uname","张三"));//查询name=张三的记录
User u = (User)criteria.uniqueResult();
* 查询uname字段中包含"三"的记录
criteria.add(Restrictions.like("uname","%三%"));
List<User> userList = criteria.list();
* 查询uid>1的记录
criteria.add(Restrictions.gt("uid",1));
List<User> userList = criteria.list();
* > gt < lt = eq >=ge <=le like between
5.10、封装Hibernate工具类 <--返回目录
import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class HibernateUtils { // 会话工厂,整个程序只有一份。 private static SessionFactory sf; static { // 1 加载配置 Configuration config = new Configuration().configure(); // 2 获得工厂 sf = config.buildSessionFactory(); // 3 关闭虚拟机时,释放SessionFactory Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { public void run() { System.out.println("虚拟机关闭!释放资源"); sf.close(); } })); } // 获得一个新的session public static Session openSession() { return sf.openSession(); } // 获得当前线程中绑定session public static Session getCurrentSession() { return sf.getCurrentSession(); } }
6、Hibernate-配置文件 <--返回目录
<property name="hbm2ddl.auto">create</property>
update:最常用,如果当前数据库中不存在表结构,自动创建表结构;如果存在表结构,并且表结构与实体一致,那么不做修改; 如果存在表结构,并且表结构与实体不一致,那么会修改表结构,会保留原有列。 create(很少用):无论是否存在表结构,每次启动Hibernate都会重新创建表结构(数据会丢失)。 create-drop(很少用):无论是否存在表结构,每次启动Hibernate都会重新创建表结构;运行结束时删除表。 validate(很少用):不会自动创建表结构,也不会自动维护表结构,只会校验表结构。如果表结构不一致,抛出异常。
方言: <property name="hibernate.dialect">org.hibernate.dialect.MySqlDialect</property>
7、Hibernate-实体配置详解-实体规则 <--返回目录
* 实体编写规则
- 提供一个无参数 public访问控制符的构造器
- 提供一个标识属性,映射数据表主键字段
- 所有属性提供public访问控制符的 set get 方法(javaBean)
- 标识属性应尽量使用基本数据类型的包装类型
** 基本数据类型和包装类型对应hibernate的映射类型相同
** 基本类型无法表达null、数字类型的默认值为0。
** 包装类默认值是null。当对于默认值有业务意义的时候需要使用包装类。
- 不要用final修饰实体 (将无法生成代理对象进行优化)
** 生成代理对象,代理对象是被代理对象的子类,final类不能被继承
* 持久化对象的唯一标识-oid&主键
- 关系数据库用主键区分同一条记录
- Hibernate使用OID来建立内存中的对象和数据库中记录的对应关系
- 结论: 对象的OID和数据库的表的主键对应。为保证OID的唯一性,应该让Hibernate来为OID赋值
* 区分自然主键和代理主键
- 主键需要具备: 不为空/不能重复/不能改变
- 自然主键: 在业务中,某个属性符合主键的三个要求。那么该属性可以作为主键列。
- 代理主键: 在业务中,不存符合以上3个条件的属性,那么就增加一个没有意义的列作为主键。
8、映射文件详解 <--返回目录
* <hibernate-mapping package="com.oy.d_hbm">
<class name="User" table="t_user">
配置了package属性,则User前面无需加包名
* <class name="com.oy.d_hbm.User" table="t_user">
- 属性dynamic-insert:动态插入,默认为false,true=>如果字段为null,不参与insert语句
- 属性dynamic-update:动态修改,默认为false,true=>如果字段为null,不参与update语句
* <id name="uid" column="uid">
- 属性length:修改表uid的数据长度,演示不成功
- unsaved-value(不常用):指定主键为什么值时,当做null来处理
** 我们建实体类的规则,主键使用包装类
- access(不推荐使用):field,那么在操作属性时,直接操作对应的字段,而不是get/set方法
* 主键生成策略
<id name="uid" column="uid">
<!-- 主键生成策略:native表示由数据库维护主键(数据库中主键设置为自增) -->
<generator class="native"></generator>
</id>
- <generator class="">主键生成策略
- 1)increment:数据库自己生成。先从数据库总查询最大的ID值,将ID值加1
** 当主键生成策略为increment,save()方法会使用语句select max(uid) from t_user来给user设置uid;
** save()方法不会使用insert语句;
** 此时,需要使用事务提交,才会使用insert语句,把数据持久化到数据库中;
- 2)identity:依赖数据的主键自增功能
** 当主键生成策略是identity,save()方法使用insert语句获取uid;
** 由于使用了insert语句,save()方法后数据已经持久化到数据库中了;
- 3)sequence:序列,依赖于数据中的序列功能(Oracle)
- 4)hilo(了解,永远用不到):Hibernate自己实现序列的算法,自己生成主键,hilo算法
- 5)native:自动根据数据库判断,identity, sequence, hilo三选一
- 6)uuid:生成不重复的32位随机字符串当做主键
- 7)assigned:自己设置主键值。一般在表的主键是自然主键时使用该策略。
* 实体其他属性<property name="" column=""></property>
- length:数据长度
- precision:小数点后的精度,(字段为double类型时使用)
- scale:有效位数,(字段为double类型时使用)
- insert(一般不用):false表示该属性是否加入inset语句
- update(一般不用):false表示该属性是否加入update语句
- not-null:知道属性的约束是否使用非空
- unique:指定属性的约束是否使用唯一
- type:表达该属性的类型,可以使用三种方式来指定属性
java类型 数据库类型 Hibernate类型
java.lang.String varchar string
posted on 2020-06-13 09:01 wenbin_ouyang 阅读(307) 评论(0) 编辑 收藏 举报