前言
记录我的Hibernate学习之路
开始
一、web内容基础
1.JavaEE三层结构
(1)表现层web层:Struts2 框架(MVC是一个表现层的设计模型)
(2)业务层sevice层:spring框架
(3)持久层 DAO层:Hibernate框架
DAO层是对数据库进行CRUD(增删改查)操作的。
Hibernate只能和数据库打交道(操作数据库)
2.MVC思想
(1)M:Model模型
(2)V:View视图
(3)C:Controller控制器
二、Hibernate框架概述
什么是Hibernate框架:
(1)Hibernate框架是应用在JavaEE三层结构中DAO层的框架
(2)在DAO层里面使用Hibernate对数据库做CRUD操作,Hibernate底层代码就是JDBC,Hibernate就是对JDBC进行封装,不需要写复杂的sql语句。
(3)Hibernate是一个开源的轻量级框架
(4)Hibernate版本:
Hibernate3.X
Hibernate4.X
Hibernate5.X(学习)
三、ORM思想介绍
1.Hibernate使用orm思想对数据库进行CRUD操作
2.在Web阶段学习JavaBean,更正确的叫法为实体类
3.orm,即object relational mapping,对象关系映射
文字描述:
(1)让实体类和数据库表进行一一的对应关系,让实体类和数据库表进行对应,让实体类中的属性和表中的字段进行对应
(2)不需要直接操作数据库,而操作表对应实体类对象
画图描述:
四、Hibernate入门
1.搭建Hibernate环境
导入Hibernate的jar包,使用Hibernate的时候,有很多日志信息输出,有时候需要导入一些其他支持日志的jar包
不要忘记mysql驱动的一些jar包
2.创建实体类
使用Hibernate的时候,不需要自己手动创建数据库表,Hibernateyou自动建表功能
3.配置实体类和数据库表的基本对应关系,映射关系
通过Hibernate配置文件来实现这种映射关系
(1)创建一个xml格式的配置文件
映射配置文件的名称和位置没有固定要求,但一般使用的是xxxx.hbm.xml
(hibernate mapping),并且在实体类所在包中创建
(2)配置文件是xml格式,在配置文件中首先引入xml约束
在hibernate里面引入的约束一般是dtd约束
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
(3)配置映射关系
<hibernate-mapping package="com.how2java.pojo">
<!-- 表示类Product对应表product_ -->
<class name="Product" table="product_">
<!-- 表示属性id,映射表里的字段id -->
<id name="id" column="id">
<!--<generator class="native"> 意味着id的自增长方式采用数据库的本地方式 -->
<generator class="native">
</generator>
</id>
<!-- 配置其他属性和表字段的对应 -->
<property name="name" />
<property name="price" />
<many-to-one name="category" class="Category" column="cid"/>
<set name="users" table="user_product" lazy="false">
<key column="pid" />
<many-to-many column="uid" class="User" />
</set>
</class>
</hibernate-mapping>
4.创建Hibernate核心配置文件
(1)核心配置文件格式也是xml,但是核心配置文件名称和位置是固定的。
位置:必须在src下面
名称:必须hibernate.cfh.xml
可见上3.(1)中图项目架构的位置
(2)引入dtd约束
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
(3)Hibernate操作过程中,只会加载核心配置文件,其他文件不会加载
第一部分:配置数据库的相关信息
第二部分:配置Hibernate相关信息
第三部分:把映射文件放到核心配置文件中
<!-- hibernate配置文件 -->
<hibernate-configuration>
<session-factory>
<!-- 第一部分:配置数据库的相关信息 -->
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8</property>
<property name="connection.username">root</property>
<property name="connection.password">admin</property>
<!-- 第二部分:配置Hibernate相关信息 -->
<!-- SQL dialect -->
<!-- 这表示使用MYSQL方言。 什么方言呢?
因为在代码层面,开发人员不用关心底层到底用Oracle还是Mysql,写的代码都是一样的。
可是Oracle和Mysql所用的sql语句的语法是有所区别的,那么这件事就交给Hibernate来做了。
这个时候就需要告诉Hibernate底层用的是什么数据库,它才知道应该用什么样的“方言” 去对话。 -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 这是Hibernate事务管理方式,即每个线程一个事务 -->
<property name="current_session_context_class">thread</property>
<!-- 这表示是否在控制台显示执行的sql语句 -->
<property name="show_sql">true</property>
<!-- 这表示是否在控制台显示执行的sql语句格式化 -->
<property name="hibertate.format_sql">true</property>
<!-- 这表示是否会自动更新数据库的表结构,有这句话,其实是不需要创建表的,因为Hibernate会自动去创建表结构
原因:使用update:如果已经有表,更新,如果没有则创建-->
<property name="hbm2ddl.auto">update</property>
<!-- 第三部分:把映射文件放到核心配置文件中 -->
<!-- 这表示Hibernate会去识别Product这个实体类 下面同理 -->
<mapping resource="com/how2java/pojo/Product.hbm.xml" />
<mapping resource="com/how2java/pojo/Category.hbm.xml" />
<mapping resource="com/how2java/pojo/User.hbm.xml" />
</session-factory>
</hibernate-configuration>
5.实现添加操作
(1)加载Hibernate核心配置文件
(2)创建SessionFactory对象
(3)使用SessionFactory创建Session对象
(4)开启事务
(5)写具体CRUD逻辑
(6)提交事务
(7)关闭资源
package com.how2java.test;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import com.how2java.pojo.Category;
import com.how2java.pojo.Product;
import com.how2java.pojo.User;
public class TestHibernate {
public static void main(String[] args) {
//加载Hibernate核心配置文件
//到src下面找到名称是hibernate.cfg.mxl
//Configuation cfg = new Configuation().configure();
//创建SessionFactory对象
//SessionFactory sessionFactory = cfg.buildSessionFactoty();
//读取hibernate.cfg.xml文件内容,创建SessionFactory
//在这个过程中,根据映射关系,在数据库中把表创建
SessionFactory sf = new Configuration().configure().buildSessionFactory();
//使用SessionFactory创建Session对象
Session s = sf.openSession();
//开启事务
//hibernate中的事务由s.beginTransaction();开始
s.beginTransaction();
/*插入
for(int i=0;i<10;i++) {
Product p = new Product();
p.setName("iphone"+i);
p.setPrice(i);
s.save(p);
}
new 了一个Product();,在数据库中还没有对应的记录,这个时候Product对象的状态是瞬时的。
通过Session的save把该对象保存在了数据库中,
该对象也和Session之间产生了联系,此时状态是持久的。
最后把Session关闭了,这个对象在数据库中虽然有对应的数据,
但是已经和Session失去了联系,相当于脱离了管理,状态就是脱管的
Product p = new Product();
p.setName("p1");
System.out.println("此时p是瞬时状态");
s.save(p);
System.out.println("此时p是持久状态");
s.getTransaction().commit();
s.close();
System.out.println("此时p是脱管状态");
sf.close();
调用Session的get方法,根据id获取对象。 除了id之外,还需要传递一个类对象,
毕竟需要知道获取的是哪个对象
除了使用get方法,还可以使用load获取对象。 请参考get和load的区别
Product p =(Product) s.get(Product.class, 6);
System.out.println("id=6的产品名称是: "+p.getName());
删除一条数据
s.delete(p);
修改数据
System.out.println(p.getName());
p.setName("iphone-modified");
s.update(p);
TestHibernate 测试many-to-one关系
Category c =new Category();
c.setName("c1");
s.save(c);
Product p = (Product) s.get(Product.class, 8);
p.setCategory(c);
s.update(p);
TestHibernate 测试one-to-many关系
Category c = (Category) s.get(Category.class, 1);
Set<Product> ps = c.getProducts();
for (Product p : ps) {
System.out.println(p.getName());
}
//TestHibernate 测试many-to-many关系
//增加3个用户
Set<User> users = new HashSet();
for (int i = 0; i < 3; i++) {
User u =new User();
u.setName("user"+i);
users.add(u);
s.save(u);
}
//产品1被用户1,2,3购买
Product p1 = (Product) s.get(Product.class, 1);
p1.setUsers(users);
s.save(p1);
*/
//hibernate中的事务由s.getTransaction().commit();结束
//在同一个事务中执行的操作,一方失败,则全部失败。
//因为这两个操作都是在一个事务中,而且第二个操作失败了,所以最后的结果是两个操作都没有生效
//在Mysql中,只有当表的类型是INNODB的时候,才支持事务,所以需要把表的类型设置为INNODB,否则无法观察到事务.
s.getTransaction().commit();
s.close();
sf.close();
}
}
看到效果:
(1)是否生成表
(2)看表中是否有记录
我做了好多例子,都在上面代码的注释里,这里就不展示了。
五.Hibernate配置文件详解
1.Hibernate映射配置文件
(1)映射配置文件的名称和位置没有固定要求
(2)映射配置文件中,标签name写实体类相关内容,其中class标签中的name属性值写实体类的路径,id标签和property标签 的name属性值写实体类属性名称
(3)id标签和peoperty标签,column属性可以不写,此时默认和name属性一样
(4)property标签中还有一个type属性,设置生成表的字段的数据类型,一般不用。因为Hibernate会自动生成相应的数据类型。
2.Hibernate核心配置文件
(1)配置要写在标签内
(2)配置时:数据库的部分是必须的,Hibernate部分是可选的,映射文件是必须的
(3)核心配置文件名称和位置是固定的
名称: hibernate.cfg.xml
位置:src下面
六、Hibernate核心api
1.Configuation
Configuration cfg = new Configuration();
cfg.configure();
到src下面找到名称是hibernate.cfg.xml配置文件,找到对象,把配置文件放到对象里面(加载核心配置文件),也有自定义路径的配置方式。
2.SessionFactory
(1)使用Configuration的对象可以创建SessionFactory对象
SessionFactory sessionFactory = cfg.buildSessionFactory();
创建SessionFactory过程中做的事情:
根据核心配置文件,有数据库配置,有映射文件部分,到数据库中根据映射关系把表创建
(2)创建SessionFactory的过程中,要不断的创建表,特别消耗资源,在Hibernate操作中,建议一个项目一般创建一个SessionFactory对象
具体实现:
写一个工具类,使用静态代码块实现,因为静态代码块只会实现一次,并且在类加载的时候执行。
3.Session
(1)Session 类似于JDBC中的 connection
(2)调用session中不同的方法来完成CRUD操作
添加save方法
修改update方法
删除delete方法
根据id查询get方法
(3)session对象是单线程对象
表示session对象不能共用,只能自己使用
4.Transaction
事务对象
(1)开启事务
Transaction tx = session.beginTransaction();
(2)事务的提交和回滚方法
tx.commit();
tx.rollback();
(3)事务的四个特性
原子性,一致性,隔离性,持久性
七、解决配置文件没有提示问题
(1)可以上网
(2)把约束文件引入到eclipse中