javaEE三层结构:
1.web层:
2.service层:spring框架
3.dao层:hibernate框架,对数据库进行增删改查(crud)操作
MVC思想:
1.m:模型
2.v:视图
3.c:控制器
框架好处:
1.少写一部分代码实现功能
什么是Hibernate框架:
1.hibernate框架应用在javaee三层结构中的dao层框架
2.在dao层里面做对数据库crud操作,使用hibernate实现crud操作,hibernate底层代码就是jdbc,hibernate对jdbc进行封装,使用hibernate好处是不需要写复杂jdbc代码
3.hibernate开源的轻量级的框架
什么是orm思想:
1.hibernate使用orm思想对数据库进行crud操作
2.在web阶段学习javabean,更正确的叫法是 实体类
3.orm:object 对象 relational 关系 mapping 映射
(1)让实体类和数据库进行一 一对应关系,让实体类首先和数据库表对应,让实体类属性和表里面的字段对应
(2)不需要直接操作数据库表,而操作表对应的实体类
(注意:什么是CRM:客户关系管理 (CRM) 是用于管理公司与当前和未来客户之间的互动的系统。)
1.创建java项目
2.导入hibernate的jar包,
3.因为使用hibernate时,有日志信息输出,hibernate本身没有日志输出的jar包,所以要导入其它日志的jar包
4.导入mysql驱动的jar包
把上面需要的Jar包复制到新建的lib目录如下:
再导入上面需要的jar包如下:
lib目录下的jar包可以展开如下图表示导入到程序中成功:
创建实体类:
类似如下(user表的实体类):
实体类 User.java:
package com.myHibernate.entity;
/**
* 用户表
* @author AUAS
*/
public class User {
/**
* Hibernate要求实体类要有一个属性是唯一的,类似与数据库表的主键
*/
//实体类里面的属性是私有的,实体类属性建议不使用基本数据类型,使用基本数据类型对应的包装类
//八个基本数据类型对应的包装类:int-Integer,char-Character,其它的都是首字母大写,比如double-Double
//使用包装类的原因如下:比如 表示学生的分数,int score;学生得了0分,int score = 0;表示学生没有参加考试。int score = 0;这样不能准确表示学生是否参加了考试还是0分,因为int score = null 是报错的。而使用包装类Integer,可以等于0或null。
private Integer id;
private String name;
private Integer password;
//私有属性使用公开的set和get方法操作
public Integer getId(){
return id;
}
public void setId(Integer id){
this.id = id;
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public Integer getPassword(){
return password;
}
public void setPassword(Integer password){
this.password = password;
}
}
实体类对象的状态(概念):
1.实体类状态有三种
(1)瞬时态:对象里面没有id值,对象与session没有关联,如下:
(2)持久态:对象里面有id值,对象与session关联,如下:
(3)托管态:对象有id值,对象与session没有关联,如下:
2.操作实体类对象的方法
(1)saveOrUpdate方法:可以实现添加,修改操作
//实体类对象状态是瞬时态,saveOrUpdate做添加操作
// User user = new User();
// user.setName("小路2");
// user.setPassword(22222);
// session.saveOrUpdate(user);
//实体类对象状态是托管态,saveOrUpdate做修改操作
user = new User();
user.setId(4);
user.setName("小路6");
user.setPassword(2);
session.saveOrUpdate(user);
//实体类对象状态是持久态,saveOrUpdate做修改操作
// user = session.get(User.class,1);
// user.setName("小想");
// session.saveOrUpdate(user);
注意:
1.以上是使用Session(Hibernate)对象管理持久化上下文(persistence context)。还有一种方法是使用EntityManager(JPA)对象管理持久化上下文(persistence context)。他们都是将Java对象持久化到数据库中去。即有两种方法来处理Hibernate中的持久性:会话(session)和实体管理器。
2.JPA和Hibernate的区别:JPA是规范,Hibernate是实现。Hibernate只是JPA规范的许多实现之一。只有一个JPA规范。但是,有很多不同的实现。DataNucleus,TopLink,EclipseLink,OpenJPA和Hibernate都提供了JPA规范的实现。
3.什么是JDBC:JDBC( Java DataBase Connectivity ) 称为 Java数据库连接 ,它是一种用于数据库访问的应用程序 API ,由一组用Java语言编写的类和接口组成,JDBC支持不同的关系数据库,这使得程序的可移植性大大加强。有了JDBC就可以用统一的语法对多种关系数据库进行访问,而不用担心其数据库操作语言的差异 。
4.MyBatis和Hibernate区别:MyBatis和Hibernate是两种不同的数据访问框架。
原理不同:MyBatis是一种基于SQL语句的持久化框架,它通过预编译SQL语句并执行,以实现数据库访问。而Hibernate是一种基于对象的持久化框架,它通过将Java对象映射到数据库表来实现数据库访问。
使用方式不同:MyBatis的使用方式更加灵活,它允许用户编写自己的SQL语句并执行,支持多种数据库查询方式(如普通查询、存储过程等)。
使用hibernate不需要自己手动创建表,hibernate会自动帮忙创建。
配置实体类和数据库表一 一对应关系(映射关系):
1.使用配置文件实现映射关系
(1)创建xml格式的配置文件(映射配置文件名和位置没有固定要求,建议:映射配置文件在实体类所在包里面创建,实体类名为.hbm.xml)
(2)配置文件是xml格式,在配置文件中首先引入xml约束,学过约束dtd,schema,在hibernate里面引入的约束是std约束
创建如下:
User.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!--引入dtd约束-->
<!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="com.myHibernate.entity.User" table="user">
<!-- id标签
属性name:实体类里面的id属性名称
属性column:生成的表字段名称
-->
<id name="id" column="id">
<!-- 设置数据库表id增长策略(主键生成策略,hibernate要求实体类里面有一个属性作为唯一值,对应表主键,主键可以不同生成策略)
native:生成表id值就是主键自动增长。会根据不同数据库识别使用不同的值,能适用所有数据库
uuid:web阶段写代码生成uuid值,hibernate帮我们自动生成uuid值。使用uuid,实体类id属性类型必须是字符串类型
increment:每次增量为1,如每次增长1,2,3
identity:自动增长,olicle不支持
sequence:序列生成器,mysql不支持
-->
<generator class="native"></generator>
</id>
<!-- 配置实体类其它属性和表字段对应关系
属性name:实体类属性名称
属性column:生成表字段名称
-->
<property name="name" column="name"></property>
<property name="password" column="password"></property>
</class>
</hibernate-mapping>
创建Hibernate的核心配置文件:
1.核心配置文件格式是xml,核心配置文件名和位置是固定的,位置必须在src目录下,名称必须是是hibernate.cfg.xml
2.引入dtd约束
3.hibernate操作过程中,只会加载核心配置文件,其它配置文件不会加载
(1)配置数据库信息
(2)配置hibernate信息
(3)把映射文件放到核心配置文件中
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:///hibernate_day01</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<!-- 第二部分: 配置hibernate信息 可选的-->
<!-- 输出底层sql语句 -->
<property name="hibernate.show_sql">true</property>
<!-- 输出底层sql语句格式 -->
<property name="hibernate.format_sql">true</property>
<!-- hibernate帮创建表,需要配置之后
update: 如果已经有表,更新,如果没有,创建
-->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 配置数据库方言
在mysql里面实现分页 关键字 limit,只能使用mysql里面
在oracle数据库,实现分页rownum
让hibernate框架识别不同数据库的自己特有的语句
-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 第三部分: 把映射文件放到核心配置文件中 必须的-->
<mapping resource="cn/itcast/entity/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>
实现添加操作(生成表,数据库是否有插入数据等):
1.加载hibernate核心配置文件
2.创建SessionFactory对象
3.使用SessionFactory创建session对象
4.开启事务
5.写具体逻辑crud操作
6.提交事务
7.关闭资源
该测试文件:
HibernateTestDemo:
package cn.itcast.hibernatetest;
import com.myHibernate.entity.User;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
public class HibernateTestDemo {
@Test
public void testAdd() {
// 第一步 加载hibernate核心配置文件
// 到src下面找到名称是hibernate.cfg.xml的配置文件,创建对象,把配置文件放到对象里面(即加载核心配置文件)
//在hibernate里面封装对象
Configuration cfg = new Configuration();
cfg.configure();
// 第二步 创建SessionFactory对象
//使用Configuration对象创建SessionFactory对象,根据核心配置文件中的数据库配置,映射文件等信息到数据库里面根据映射关系创建数据库表。<property name="hibernate.hbm2ddl.auto">update</property> <!-- hibernate 需要配置之后才帮忙创建表;update:表示已经有表,更新,如果没有,创建-->在hibernate.cfg.xml配置文件中有这句<property>才会创建数据库表。
//读取hibernate核心配置文件内容,创建sessionFactory
//在过程中,根据映射关系,在配置数据库里面把表创建
SessionFactory sessionFactory = cfg.buildSessionFactory();
// SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
// 第三步 使用SessionFactory创建session对象
// session类似于jdbc中的connection,调用session里面的不同方法实现crud操作
//添加save方法;修改update方法;删除delete方法;根据id查询 get方法
//session对象单线程对象,session对象不能共用,只能自己使用
Session session = sessionFactory.openSession();
// 第四步 开启事务
// 事务提交tx.commit()和回滚tx.rollback()
//事务的四个特性:原子性(要么全部成功,要么全部失败);
//一致性(操作之前之后总数据一致,如付款,一个多了多少,另一个就少多少;
//隔离性(多个事务操作同一条记录,互不影响);
//持久性(提交后,保存在数据库)。
//不考虑隔离性产生问题:胀读;不可重复读;虚读
//mysql默认隔离级别repeatable read
//事务代码规范写法:
//try{
// 开启事务
// 提交事务
//}catch(){
// 回滚事务
//}finally{
// 关闭
//}
Transaction tx = session.beginTransaction();
// 第五步 写具体逻辑 crud操作
//1.添加功能
// User user = new User();
// user.setUsername("小马");
// user.setPassword("1314520");
// user.setAddress("美国");
// //调用session的方法实现添加
// session.save(user);
//2.查询操作
//根据id查数据,session里面的get方法,第一个参数:实体类的class,第二个参数:id值
//User user = session.get(User.class,1);
//System.out.println(user);
//3.修改操作
//修改id=1的name
//根据id查询
User user = session.get(User.class,1);
//向返回的user对象里面设置修改之后的值
user.setName("小鹿");
//调用session的update方法修改,(执行过程:到user对象里面找到id,根据id进行修改)
session.update(user);
//4.删除操作
//根据id查询对象
user = session.get(User.class,2);
//执行过程,到user对象中查到主键id,删除对应id的数据
session.delete(user);
// 第六步 提交事务
tx.commit();
// 第七步 关闭资源
session.close();
sessionFactory.close();
}
}
上面的第一步 加载hibernate核心配置文件和第二步 创建SessionFactory对象可以直接使用下面这句使用一个静态工具类HibernateUtils代替:
SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
静态工具类HibernateUtils如下:
package com.myHibernate.utils;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
/**
* hibernate sessionFactory静态工具栏
* @author AUAS
*/
public class HibernateUtils {
static Configuration configuration = null;
static SessionFactory sessionFactory = null;
//静态代码块实现
static {
//加载核心配置文件
configuration = new Configuration();
configuration.configure();
//创建SessionFactory对象
sessionFactory = configuration.buildSessionFactory();
}
/**
* 提供方法返回sessionFactory
*/
public static SessionFactory getSessionFactory(){
return sessionFactory;
}
}
使用上面这个工具类的好处:静态代码块实现,在类加载时候执行,而且只执行一次。
成功运行测试文件后,会在数据库看到新建了一个t_user表如下:
注意:
报错一:如果没有出现上面的表,报错如下(是因为对于Maven工程,编译的工作是由Maven程序来完成的,而Maven默认只会把src/main/resources文件夹下的文件拷贝到target/classes文件夹下,所以.hbm.xml都不会被复制到/target/calsses文件夹下,所以Hibernate框架在运行的时候,就会报找不到*.hbm.xml的错误。所以在pom.xml配置文件加上下面的内容即可):
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.myHibernate.study</groupId>
<artifactId>myHibernate</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>myHibernate</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.1.0.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
<build>
<!-- 把src/main/java下的所有xml文件,src/main/resources下的xml和properties文件也添加到target目录下。
不写下面这些配置,默认是xml和properties文件不会添加到target目录下的-->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
</resource>
</resources>
</build>
</project>
报错二:如果出现这个报错,是因为未引入log4j的依赖或未配置log4j.properties文件
在pom.xml文件插入如下代码:
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
在src/main/resources目录下添加log4j.properties文件如下:
log4j.rootLogger=debug, stdout, R
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
# Pattern to output the caller's file name and line number.
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=example.log
log4j.appender.R.MaxFileSize=100KB
# Keep one backup file
log4j.appender.R.MaxBackupIndex=5
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n
HIbernate的一级缓存:
1.缓存:
(1)数据存到数据库里面,数据库本身是文件系统,使用流方式操作文件效率不是很好。
(2)把数据存到内存里面,不需要使用流方式,可以直接读取内存中数据
(3)把数据放到内存中,提供读取效率
2.Hibernate缓存:
(1)hibernate框架提供很多优化方式,hibernate的缓存就是一个优化方式
(2)hibernate缓存特点:
第一类 hibernate的一级缓存
(1)hibernate的一级缓存默认打开
(2)hibernate的一级缓存使用范围,是session范围,从session创建到session关闭范围
(3)hibernate的一级缓存中,存储数据必须持久态数据
第二类 hibernate的二集缓存
(1)目前已经不使用了,替代技术redis
(2)二级缓存默认不是打开的,需要配置
(3)二级缓存使用范围,是sessionFactory范围
一级缓存例子:当有两条一样的查询语句,先查缓存,再查数据库,如下:
一级缓存特性:持久态自动更新数据库:
执行过程:
Hibernate绑定session:
1 session类似于jdbc的connection,之前web阶段学过 ThreadLocal
2 实现与本地线程绑定session
3 获取与本地线程session
(1)在hibernate核心配置文件中配置
<!-- 在hibernate核心配置文件中配置 -->
<property name="hibernate.current_session_context_class">thread</property>
(2)调用sessionFactory里面的方法得到
//提供返回与本地线程的session的方法
public static Session getSessionobject() {
return sessionFactory.getCurrentSession();
}
4 获取与本地线程绑定session时候,关闭session报错,不需要手动关闭了
HIbernate的api使用:
Query对象:
1.使用query对象,不需要写sql语句,但是写hql语句
(1)hql:hibernate query language,hibernate提供查询语言,这个hql语句和普通sql语句很相似
(2)hql和sql语句区别:
使用sql操作表和表字段
使用hql操作实体类和属性
2.查询所有hql语句
(1)from 实体类名称
3 Query对象使用
(1)创建Query对象
(2)调用query对象里面的方法得到结果
package cn.itcast.hibernatetest;
import com.myHibernate.entity.User;
import com.myHibernate.utils.HibernateUtils;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
import java.util.List;
public class HibernateQueryDemo {
@Test
public void testSelect() {
SessionFactory sessionFactory = null;
Session session = null;
Transaction transaction = null;
try {
sessionFactory = HibernateUtils.getSessionFactory();
//提供返回与本地线程的session的方法
session = HibernateUtils.getSessionObject();
//开启事务
transaction = session.beginTransaction();
//1.创建Query对象
//方法里面写hql语句
Query query = session.createQuery("FROM User");
//2.调用query对象里面的方法得到结果
List<User> userList = query.list();
for (User user:userList) {
System.out.println("333333333333");
System.out.println(user);
}
//提交事务
transaction.commit();
} catch (Exception e) {
e.printStackTrace();
//回滚事务
transaction.rollback();
} finally {
//关闭操作
// session.close();
// sessionFactory.close();
}
}
}
Critia对象:
1 使用这个对象查询操作,但是使用这个对象时候,不需要写语句,直接调用方法实现
2 实现过程
(1)创建criteria对象
(2)调用对象里面的方法得到结果
package cn.itcast.hibernatetest;
import com.myHibernate.entity.User;
import com.myHibernate.utils.HibernateUtils;
import org.hibernate.*;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
import java.util.List;
public class HibernateQueryDemo {
@Test
public void testSelect() {
SessionFactory sessionFactory = null;
Session session = null;
Transaction transaction = null;
try {
sessionFactory = HibernateUtils.getSessionFactory();
//提供返回与本地线程的session的方法
session = HibernateUtils.getSessionObject();
//开启事务
transaction = session.beginTransaction();
//1.创建criteria对象
//方法里面参数是实体类class
Criteria criteria = session.createCriteria(User.class);
//2.调用方法得到结果
List<User> userList = criteria.list();
for (User user:userList) {
System.out.println("333333333333");
System.out.println(user);
}
//提交事务
transaction.commit();
} catch (Exception e) {
e.printStackTrace();
//回滚事务
transaction.rollback();
} finally {
//关闭操作
// session.close();
// sessionFactory.close();
}
}
}
SQLQuery对象:
1 使用hibernate时候,调用底层sql实现
2 实现过程
(1)创建对象
(2)调用对象的方法得到结果
返回list集合每部分是数组
返回list中每部分是对象形式
package cn.itcast.hibernatetest;
import com.myHibernate.entity.User;
import com.myHibernate.utils.HibernateUtils;
import org.hibernate.*;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
public class HibernateQueryDemo {
@Test
public void testSelect() {
SessionFactory sessionFactory = null;
Session session = null;
Transaction transaction = null;
try {
sessionFactory = HibernateUtils.getSessionFactory();
//提供返回与本地线程的session的方法
session = HibernateUtils.getSessionObject();
//开启事务
transaction = session.beginTransaction();
//1.创建SQLQuery对象
//方法里面参数是普通sql语句
SQLQuery sqlQuery = session.createSQLQuery("SELECT * FROM t_user");
// //2.调用sqlQuery里面的方法得到结果
// List<Object[]> userList = sqlQuery.list();
// for (Object[] objects :userList) {
// System.out.println("333333333333");
// System.out.println(Arrays.toString(objects));
// }
//返回的list中每部分是对象形式
sqlQuery.addEntity(User.class);
//调用sqlQuery里面的方法
List<User> userList = sqlQuery.list();
for (User user :userList) {
System.out.println("333333333333");
System.out.println(user);
}
//提交事务
transaction.commit();
} catch (Exception e) {
e.printStackTrace();
//回滚事务
transaction.rollback();
} finally {
//关闭操作
// session.close();
// sessionFactory.close();
}
}
}