ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
[TOC] # 导入依赖 ~~~ <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.10</version> <scope>provided</scope> </dependency> <!-- 添加Junit依赖 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- 钱相关 --> <dependency> <groupId>org.joda</groupId> <artifactId>joda-money</artifactId> <version>1.0.1</version> </dependency> <!-- 类型映射相关 --> <dependency> <groupId>org.jadira.usertype</groupId> <artifactId>usertype.core</artifactId> <version>6.0.1.GA</version> </dependency> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <!-- <version>5.1.48</version>--> <version>8.0.18</version> </dependency> <!-- 添加hibernate依赖包 --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.2.6.Final</version> </dependency> ~~~ # 配置hibernate.cfg.xml 核心配置文件 位置必须是在src下面 名称: 必须是hibernate.cfg.xml ~~~ <?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- mysql账户名 --> <property name="connection.username">root</property> <!-- mysql密码 --> <property name="connection.password">root</property> <!-- mysql驱动 --> <property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property> <!-- mysql连接URL --> <property name="connection.url">jdbc:mysql:///app?useUnicode=true&amp;characterEncoding=UTF-8</property> <!-- 数据库方言 --> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <!-- 显示sql语句 --> <property name="show_sql">true</property> <!-- 格式化sql语句 --> <property name="format_sql">true</property> <!-- 根据需要创建数据库 --> <!-- hbm2ddl.auto的取值 * none : 不用Hibernate自动生成表. * create : 每次都会创建一个新的表.(测试) * create-drop : 每次都会创建一个新的表,执行程序结束后删除这个表(测试) * update : 如果数据库中有表,使用原来的表,如果没有表,创建一个新的表,可以更新表结构 * validate : 只会使用原有的表,对映射关系进行校验 --> <property name="hbm2ddl.auto">create</property> </session-factory> </hibernate-configuration> ~~~ idea添加配置文件 `project structure`->Facets->+号->Hibernate ![](https://img.kancloud.cn/02/02/020209e924aa26941872ca607a3accff_472x320.png) ![](https://img.kancloud.cn/33/0b/330b6199e9e4cfcd5439948692d33a4f_836x147.png) # idea生成 创建goods表 ![](https://img.kancloud.cn/97/e3/97e3cc326e3f9d519a89d6dab76bc1b8_191x164.png) ![](https://img.kancloud.cn/77/82/7782a16347e57d86adbd54b71dad18b1_1054x1350.png) **生成hibernate的数据库映射类** ![](https://img.kancloud.cn/02/07/0207c1358f6ab3c0dc0586609bfa455d_874x786.png) ![](https://img.kancloud.cn/a1/08/a108d544a943a68608e8713a215a4c83_731x493.png) Choose Data Source选择数据库源 package选择的是放映射类的文件夹 ![](https://img.kancloud.cn/c8/e9/c8e9b3f45c6f121a6046a2e09507ca3b_492x729.png) 这一步OK之后,查看最终结果 **不过生成的不好,类型应该用包装类型不要用基本类型** **比如int类型分数,0分和没有考null,用包装类能表示** **给映射类加一个无参构造方法,有参构造方法可加可不加** **配置hibernate.cfg.xml,添加刚刚生成的映射类** ~~~ <!-- 格式化sql语句 --> <property name="format_sql">true</property> <!-- 根据需要创建数据库 --> <property name="hbm2ddl.auto">create</property> <mapping class="com.xubafiu.Goods"></mapping> </session-factory> </hibernate-configuration> ~~~ # 测试 ~~~ import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.junit.After; import org.junit.Before; import org.junit.Test; public class TestGoods { private SessionFactory sessionFactory; private Session session; private Transaction transaction; @Before public void init() { //创建配置对象,加载核心配置文件,src下的hibernate.cfg.xml,也可以指定位置.configure("/path/xml"); Configuration configuration = new Configuration().configure(); //创建sessionFactory会话工厂 sessionFactory = configuration.buildSessionFactory(); //开启session会话,类似连接 session = sessionFactory.openSession(); //开启事务 transaction = session.beginTransaction(); } @After public void destory() { //事务提交, 事务回滚是transaction.rollback(); transaction.commit(); //关闭session会话 session.close(); //关闭sessionFactory会话工厂 sessionFactory.close(); } @Test public void testGoods() { //生成对象 Goods goods = new Goods(1, "abc", 2333.33); //保存对象进数据库 session.save(goods); } } ~~~ # xml方式 在实体类所在包里面创建,实体名称.hbm.xml ![](https://img.kancloud.cn/85/bd/85bdc9e8e0008409f8b95c96a6dc4da1_1306x1398.png) ## 映射配置文件 ~~~ <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- package属性:填写一个包名.在元素内部凡是需要书写完整类名的属性,可以直接写简答类名了. --> <!-- <hibernate-mapping package="domain"> --> <hibernate-mapping> <!-- 1. 配置类和表对应 class标签 name属性: 实体类全路径 table属性: 数据库表名称 --> <class name="dao.Goods" table="goods"> <!-- 2. 配置实体类和表id对应 hibernate要求实体类有一个属性唯一值 要求表有字段作为唯一值 --> <!-- id元素:配置主键映射的属性 name: 填写主键对应属性名 column(可选): 填写表中的主键列名.默认值:列名会默认使用属性名 type(可选):填写列(属性)的类型.hibernate会自动检测实体的属性类型. 每个类型有三种填法: java类型|hibernate类型|数据库类型 not-null(可选):配置该属性(列)是否不能为空. 默认值:false length(可选):配置数据库中列的长度. 默认值:使用数据库类型的最大长度 --> <id name="id" column="id"> <!-- 设置数据库表id增长策略, native: 生成表id值就是主键自动增长 --> <generator class="native" /> </id> <!-- 配置其他属性和表字段对应 --> <!-- property元素:除id之外的普通属性映射 name: 填写属性名 column(可选): 填写列名 type(可选):填写列(属性)的类型.hibernate会自动检测实体的属性类型. 每个类型有三种填法: java类型(要写全了java.lang.string)|hibernate类型(string)|数据库类型 not-null(可选):配置该属性(列)是否不能为空. 默认值:false length(可选):配置数据库中列的长度. 默认值:使用数据库类型的最大长度 --> <property name="name" column="name" /> <property name="price" column="price" /> </class> </hibernate-mapping> ~~~ 如果用这个的话,核心配置文件要修改 **在核心配置文件中添加** ~~~ <!-- 把映射配置文件放到核心配置文件中 --> <mapping resource="dao/Goods.hbm.xml" /> </session-factory> </hibernate-configuration> ~~~ # SessionFactory 1. 使用configuration对象创建sessionFactory对象 根据核心配置文件中,有数据库配置,有映射文件部分,到数据库里面根据映射关系把表创建 ~~~ <!-- 根据需要创建数据库 --> <property name="hbm2ddl.auto">create</property> ~~~ 2. 创建sessionFactory过程中,这个过程特别耗资源,一个项目只建议创建一个 # Hibernate执行原理总结 hibernate工作原理: 1. 通过Configuration().configure();读取并解析hibernate.cfg.xml配置文件。 2. 由hibernate.cfg.xml中的读取解析映射信息。 3. 通过config.buildSessionFactory();//得到sessionFactory。 4. sessionFactory.openSession();//得到session。 5. session.beginTransaction();//开启事务。 6. persistent operate; 7. session.getTransaction().commit();//提交事务 8. 关闭session; 9. 关闭sessionFactory; # session常用方法 ~~~ save 保存对象 update 修改操作 delete删除 get/load 根据id进行查询 savenOrUpdate 执行save或update操作 createQuery()获取一个Query对象 CreateSQLQUery()获取一个可以操作sql的SQLQuery对象 createCriteria() 获取一个Criteria它可以完成条件查询 ~~~ # Transaction事务 Transaction接口主要用于管理事务,它是hibernate的事务接口,对底层的事务进行了封装。使用它可以进行事务操作。 commit 事务提交 rollback 事务回滚 问题: 获取一个Transaction对象 ~~~ Session.beginTransaction(); ~~~ 问题: 如果在程序中没有开启事务,是否存在事务? 有事务,session的每一个操作就会开启一个事务。 默认不自动提交 ~~~ <!-- 用于设置事务提交方式 --> <property name="hibernate.connection.autocommit">false</property> ~~~ # 什么是持久化类? Persistent Object (PO) PO=POJO+hbm映射配置 对于hibernate中的PO编写规则: 1. 必须提供一个无参数的public构造方法 2. 所有属性要private ,对外提供public 的get/set方法 3. 在PO类必须提供一个标识属性,让它与数据库中的主键对应,我们管这个属性叫OID 4. PO类中的属性尽量使用基本数据类型的包装类. Int->Integer double-->Double float->Float 5. PO类它不能使用final修饰符 # OID作用 ~~~ OID指的是与数据库中表的主键对应的属性。 ~~~ Hibernate框架它是通过OID来区分不同的PO对象,如果在内存中有两个相同的OID对象,那么hibernate认为它们是同一个对象。 # 为什么PO类属性它要使用包装类型? 使用基本数据类型是没有办法去描述不存在概念,如果使用包装类型,它就是一个对象,对于对象它的默认值是null. 但是基础类型,比如int类型表示分数,没有考应该是null,这个int表示不了 # PO类不可以使用final修饰?(hibernate中的get/load方法的区别) ~~~ Get/load方法它们都是根据id去查询对象。 ~~~ 1. get直接得到了一个持久化类型对象,它就是立即查询操作 load它得到的是持久化类开的代理类型对象(子类对象)。它采用了一种延迟策略来查询数据。 2. get方法在查询时,如果不存在返回null load方法在查询时,如果不存在,会产生异常 ObjectNotFoundException.