目录
一、什么是hibernate
二、编写一个hibernate的maven项目
三、hibernate和mybatis的对比
四、hibernate的creteria和mybatis的example.creteria
Gitee仓库:https://gitee.com/inandout/hibernate---nange/tree/dev/
百度百科
Hibernate官网
Mybatis官网
使用传统的JDBC开发应用系统时,如果是小型应用系统,并不觉得有什么麻烦,但是对于大型应用系统的开发,使用JDBC就会显得力不从心。例如对几十、几百张包含几十个字段的表进行插入操作时,编写的SQL语句不但很长,而且繁琐,容易出错;在读取数据时,需要写多条getXxx语句从结果集中取出各个字段的信息,不但枯燥重复,并且工作量非常大。为了提高数据访问层的编程效率,Gavin King开发出了一个当今最流行的的ORM框架,它就是Hibernate框架。
所谓的ORM就是利用描述对象和数据库表之间映射的元数据,自动把Java应用程序中的对象,持久化到关系型数据库的表中。通过操作Java对象,就可以完成对数据库表的操作。可以把ORM理解为关系型数据和对象的一个纽带,开发人员只需要关注纽带一端映射的对象即可。ORM原理如下图所示。
说那么多,无非就是想说说ORM是个什么东西,对象关系映射(英语:Object Relation Mapping,简称ORM,或O/RM,或O/R mapping),指的是将一个Java中的对象与关系型数据库中的表建立一种映射关系,从而操作对象就可以操作数据库中的表。
与其它操作数据库的技术相比,Hibernate具有以下几点优势:
总结:Hibernate是企业级开发中的主流框架,映射的灵活性很出色,并且它支持很多关系型数据库。
这个课程是我自己找的学习的,这个项目都是跟着他做的
课程地址:1、Hibernate快速入门-1_哔哩哔哩_bilibili
项目结构
导入依赖
mysql
mysql-connector-java
5.1.47
org.hibernate
hibernate-core
5.4.10.Final
org.projectlombok
lombok
1.18.18
src/main/java
**/*.xml
src/main/resources
**/*.xml
编写hibernate配置文件 hibernate.cfg.xml
root
com.mysql.jdbc.Driver
jdbc:mysql://localhost:3306/hibernate?useSSL=false&useUnicode=true&characterEncoding=UTF-8
10
10000
5000
30
5
10
org.hibernate.dialect.MySQLDialect
true
true
编写实体类
@Data
public class People {
private int id;
private String name;
private Double money;
}
编写实体类映射文件 People.hbm.xml
编写测试方法
public class test1 {
public static void main(String[] args) {
//创建Configuration
Configuration configuration = new Configuration().configure("hibernate.cfg.xml");
//获取SessionFactory
SessionFactory sessionFactory = configuration.buildSessionFactory();
//获取Session
Session session = sessionFactory.openSession();
People people = new People();
people.setId(1);
people.setName("张三");
people.setMoney(1000.0);
session.save(people);
session.beginTransaction().commit();
session.close();
}
}
启动项目测试
客户和订单:每个客户可以购买多个产品,⽣成多个订单,但是⼀个订单只能属于⼀个客户,所以客户
是⼀,订单是多。
新建实体类 Customer.java
@Data
public class Customer {
private int id;
private String name;
private Set ordersSet;
@Override
public String toString() {
return "Customer{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
Orders.java
@Data
public class Orders {
private int id;
private String name;
private Customer customer;
}
编写实体类映射文件 Customer.hbm.xml
Orders.hbm.xml
编写测试方法
/**
* 基础的一对多
*/
public class test2 {
public static void main(String[] args) {
// 创建Configuration
Configuration configuration = new Configuration().configure("hibernate.cfg.xml");
// 获取SessionFactory
SessionFactory sessionFactory = configuration.buildSessionFactory();
// 获取Session
Session session = sessionFactory.openSession();
// 创建 Customer
Customer customer = new Customer();
customer.setName("张三");
// 创建 Orders
Orders orders = new Orders();
orders.setName("订单1");
// 建⽴关联关系
orders.setCustomer(customer);
// 保存
session.save(customer);
session.save(orders);
// 提交事务
session.beginTransaction().commit();
session.close();
}
}
启动项目测试
学⽣选课:⼀⻔课程可以被多个学⽣选择,⼀个学⽣可以选择多⻔课程,学⽣是多,课程也是多。
数据库中是通过两个⼀对多关系来维护的,学⽣和课程都是主表,额外增加⼀张中间表作为从表,两张
主表和中间表都是⼀对多关系。
新建实体类 Account.java
@Getter
@Setter
@ToString
public class Account {
private int id;
private String name;
private int age;
private Set courseSet;
}
Course.java
@Getter
@Setter
public class Course {
private int id;
private String name;
private Set accountSet;
@Override
public String toString() {
return "Course{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
编写实体类映射文件 Account.hbm.xml
Course.hbm.xml
编写测试方法 查询
/**
* 级联查询
*/
public class test6 {
public static void main(String[] args) {
//创建Configuration
Configuration configuration = new Configuration().configure("hibernate.cfg.xml");
//获取SessionFactory
SessionFactory sessionFactory = configuration.buildSessionFactory();
//获取Session
Session session = sessionFactory.openSession();
// 条件查询
Course course = session.get(Course.class, 1);
System.out.println(course);
System.out.println(course.getAccountSet());
Account account = session.get(Account.class, 1);
System.out.println(account);
session.close();
}
}
新增
/**
* 级联新增
*/
public class test7 {
public static void main(String[] args) {
//创建Configuration
Configuration configuration = new Configuration().configure("hibernate.cfg.xml");
//获取SessionFactory
SessionFactory sessionFactory = configuration.buildSessionFactory();
//获取Session
Session session = sessionFactory.openSession();
Course course = new Course();
course.setName("java");
Account account = new Account();
account.setName("jilian");
Set courses = new HashSet<>();
courses.add(course);
account.setCourseSet(courses);
session.save(course);
session.save(account);
session.beginTransaction().commit();
session.close();
}
}
启动项目测试
HQL:Hibernate Query Language,是 Hibernate 框架提供的⼀种查询机制,它和 SQL 类似,不同的是 HQL 是⾯向对象的查询语句,让开发者能够以⾯向对象的思想来编写查询语句,对 Java 编程是⼀种友好的⽅式。
HQL 不能直接参与数据库的交互,是中间层语⾔。
Java ---》HQL ---〉Hibernate ---》SQL ---〉DB
HQL 只能完成查询、修改、删除,新增是⽆法操作的。
HQL 进⾏查询,from 关键字后⾯不能写表名,必须写表对应的实体类名。
① 列表查询
public class HQL1 {
public static void main(String[] args) {
//创建 Configuration
Configuration configuration = new Configuration().configure("hibernate.cfg.xml");
//获取 SessionFactory
SessionFactory sessionFactory = configuration.buildSessionFactory();
//获取 Session
Session session = sessionFactory.openSession();
// 列表查询
String hql = "from People";
Query query = session.createQuery(hql);
List list = query.list();
for (People people : list) {
System.out.println(people);
}
session.close();
}
}
② 分页查询
public class HQL2 {
public static void main(String[] args) {
//创建 Configuration
Configuration configuration = new Configuration().configure();
//获取 SessionFactory
SessionFactory sessionFactory = configuration.buildSessionFactory();
//获取 Session
Session session = sessionFactory.openSession();
// 分页查询
String hql = "from People";
Query query = session.createQuery(hql);
query.setFirstResult(1);
query.setMaxResults(3);
List list = query.list();
for (People people : list) {
System.out.println(people);
}
session.close();
}
}
③ where条件查询 + 模糊查询 + 排序
public class HQL3 {
public static void main(String[] args) {
//创建 Configuration
Configuration configuration = new Configuration().configure();
//获取 SessionFactory
SessionFactory sessionFactory = configuration.buildSessionFactory();
//获取 Session
Session session = sessionFactory.openSession();
// where条件查询 + 模糊查询 + 排序
String hql = "from People where id = 6 and name like '%三%' order by id asc";
Query query = session.createQuery(hql);
if (query.list() != null) {
People people = (People) query.list().get(0);
System.out.println(people);
} else {
System.out.println("查询结果为空");
}
session.close();
}
}
④ Select条件选取
public class HQL4 {
public static void main(String[] args) {
//创建 Configuration
Configuration configuration = new Configuration().configure();
//获取 SessionFactory
SessionFactory sessionFactory = configuration.buildSessionFactory();
//获取 Session
Session session = sessionFactory.openSession();
// Select条件选取
String hql = "select name from People where id = 6";
Query query = session.createQuery(hql);
String name = (String) query.uniqueResult();
System.out.println(name);
session.close();
}
}
⑤ 占位符
public class HQL5 {
public static void main(String[] args) {
//创建 Configuration
Configuration configuration = new Configuration().configure();
//获取 SessionFactory
SessionFactory sessionFactory = configuration.buildSessionFactory();
//获取 Session
Session session = sessionFactory.openSession();
// 占位符
String hql = "from People where name = :name";
Query query = session.createQuery(hql);
query.setString("name", "张三");
List list = query.list();
for (People people : list) {
System.out.println(people);
}
session.close();
}
}
⑥ 多对多级联查询
public class HQL6 {
public static void main(String[] args) {
//创建 Configuration
Configuration configuration = new Configuration().configure();
//获取 SessionFactory
SessionFactory sessionFactory = configuration.buildSessionFactory();
//获取 Session
Session session = sessionFactory.openSession();
// 级联查询
String hql1 = "from Customer where name = :name";
Query query1 = session.createQuery(hql1);
query1.setString("name", "张三");
Customer customer = (Customer) query1.uniqueResult();
String hql2 = "from Orders where customer = :customer";
Query query2 = session.createQuery(hql2);
query2.setEntity("customer", customer);
List list = query2.list();
for (Orders orders : list) {
System.out.println(orders);
}
session.close();
}
}
Hibernate与MyBatis都可以是通过SessionFactoryBuider由XML配置文件生成SessionFactory,然后由SessionFactory 生成Session,最后由Session来开启执行事务和SQL语句。
其中SessionFactoryBuider,SessionFactory,Session的生命周期都是差不多的。Hibernate和MyBatis都支持JDBC和JTA事务处理。
(1)hibernate是全自动,而mybatis是半自动
hibernate完全可以通过对象关系模型实现对数据库的操作,拥有完整的JavaBean对象与数据库的映射结构来自动生成sql。而mybatis仅有基本的字段映射,对象数据以及对象实际关系仍然需要通过手写sql来实现和管理。
(2)hibernate数据库移植性远大于mybatis
hibernate通过它强大的映射结构和hql语言,大大降低了对象与数据库(Oracle、MySQL等)的耦合性,而mybatis由于需要手写sql,因此与数据库的耦合性直接取决于程序员写sql的方法,如果sql不具通用性而用了很多某数据库特性的sql语句的话,移植性也会随之降低很多,成本很高。
(3)hibernate拥有完整的日志系统,mybatis则欠缺一些
hibernate日志系统非常健全,涉及广泛,包括:sql记录、关系异常、优化警告、缓存提示、脏数据警告等;而mybatis则除了基本记录功能外,功能薄弱很多。
(4)mybatis相比hibernate需要关心很多细节
hibernate配置要比mybatis复杂的多,学习成本也比mybatis高。但也正因为mybatis使用简单,才导致它要比hibernate关心很多技术细节。mybatis由于不用考虑很多细节,开发模式上与传统jdbc区别很小,因此很容易上手并开发项目,但忽略细节会导致项目前期bug较多,因而开发出相对稳定的软件很慢,而开发出软件却很快。hibernate则正好与之相反。但是如果使用hibernate很熟练的话,实际上开发效率丝毫不差于甚至超越mybatis。
(5)sql直接优化上,mybatis要比hibernate方便很多
由于mybatis的sql都是写在xml里,因此优化sql比hibernate方便很多。而hibernate的sql很多都是自动生成的,无法直接维护sql;虽有hql,但功能还是不及sql强大,见到报表等变态需求时,hql也歇菜,也就是说hql是有局限的;hibernate虽然也支持原生sql,但开发模式上却与orm不同,需要转换思维,因此使用上不是非常方便。总之写sql的灵活度上hibernate不及mybatis。
(6)缓存机制上,hibernate要比mybatis更好一些
MyBatis的二级缓存配置都是在每个具体的表-对象映射中进行详细配置,这样针对不同的表可以自定义不同的缓存机制。并且Mybatis可以在命名空间中共享相同的缓存配置和实例,通过Cache-ref来实现。
而Hibernate对查询对象有着良好的管理机制,用户无需关心SQL。所以在使用二级缓存时如果出现脏数据,系统会报出错误并提示。
3、举个形象的比喻
MyBatis:机械工具,使用方便,拿来就用,但工作还是要自己来作,不过工具是活的,怎么使由我决定。(小巧、方便、高效、简单、直接、半自动)
Hibernate:智能机器人,但研发它(学习、熟练度)的成本很高,工作都可以摆脱他了,但仅限于它能做的事。(强大、方便、高效、复杂、绕弯子、全自动)
① (Hibernate Query Language):面向对象的查询语言,与SQL不同,HQL中的对象名是区分大小写的(除了JAVA类和属性其他部分不区分大小写);HQL中查的是对象而不是和表,并且支持多态
② Criteria
是一种比HQL更面向对象的查询方式;Hibernate 设计了 CriteriaSpecification 作为 Criteria 的父接口
Criterion:是 Criteria 的查询条件。Criteria 提供了 add(Criterion criterion) 方法来添加查询条件。
Criterion 接口的主要实现包括: Example 、 Junction 和 SimpleExpression 。
Criterion 的实例可以通过 Restrictions 工具类来创建,Restrictions 提供了大量的静态方法,如 eq (等于)、 ge (大于等于)、 between 等来方法的创建 Criterion 查询条件(SimpleExpression 实例)。除此之外, Restrictions 还提供了方法来创建 conjunction 和disjunction 实例,通过往该实例的 add(Criteria) 方法来增加查询条件形成一个查询条件集合。
源码
③ 编写列表查询方法
public class creteria1 {
public static void main(String[] args) {
//创建 Configuration
Configuration configuration = new Configuration().configure("hibernate.cfg.xml");
//获取 SessionFactory
SessionFactory sessionFactory = configuration.buildSessionFactory();
//获取 Session
Session session = sessionFactory.openSession();
// 列表查询
Criteria criteria = session.createCriteria(People.class);
criteria.add(Restrictions.eq("name", "张三"));
List list = criteria.list();
for (People people : list) {
System.out.println(people);
}
session.close();
}
}
启动项目测试
① 为什么要有Criteria
Criteria英文是标准、条件和准则的意思
在使用常规的mybatis时,我们经常碰到的问题就是条件式查询。在一个查询界面,查询条件较多,并且运算符并不总是 = 时,在后台就需要拼装 sql语句。这种处理方式肯定不是使用mybatis的初衷,对于使用了hibernate的我来说,如果mybatis也有一套criteria查询就好了。在具体实现中,我们只需要按照hibernate的处理方式定义好相应的criteria,最后传递给mybatis,其自身处理相应的条件和参数信息,最终返回相应的数据即可。
② 如何生成Example类?
mybatis的的配置文件可以使用mybatis-generator工具生成,它就可以帮我们生成example类。
generator依赖地址
mybatis-generator会为每个字段产生Criterion,为底层的mapper.xml创建动态sql。如果表的字段比较多,产生的example类会十分庞大。理论上通过example类可以构造你想到的任何筛选条件。
③ 分析生成的Example中的元素
Criteria
Criteria包含一个Cretiron的集合,每一个Criteria对象内包含的Cretiron之间是由AND连接的,是逻辑与的关系。
Cretiron
各种sql的表达式方法,eq()、like()、between()、in()、lessThan()、isNull()
oredCriteria
Example内有一个成员叫oredCriteria,是Criteria的集合,就想其名字所预示的一样,这个集合中的Criteria是由OR连接的,是逻辑或关系。oredCriteria就是ORed Criteria。
其他
Example类的distinct字段用于指定DISTINCT查询。
orderByClause字段用于指定ORDER BY条件,这个条件没有构造方法,直接通过传递字符串值指定。
④ 编写测试方法
UserExample example = new UserExample();
Criteria criteria = example.createCriteria();
criteria.andUsernameEqualTo("wyw");
criteria.andUsernameIsNull();
example.setOrderByClause("username asc,email desc");
List>list = XxxMapper.selectByExample(example);