Hibernate day_02

  1. 持久化类以及编写规则.

持久化类就是我们说的实体类(符合 JavaBean 的规则)。
以后分包:entity(实体),pojo(简单的 Java 对象),domian(域对象)
1. 属性的声明必须使用私有的 private
2. 通过 get,set 方法获得设置和获得属性值
3. 属性的声明不能使用 final 关键字
4. [可选]建议实现一个序列接口 Serializable.如果需要将对象缓存到本地文件,必须加上

  1. 主键生成策略

所谓的主键生成策略,就是 Hibernate 提供了多种生成主键值的方法

常用的策略有:increment identity sequence native uuid assigned

  1. increment策略

不使用数据库的本地的增长策略,而是由程序(Hibernate框架)产生一个自增长的ID 值,赋予数据库.

<generator class="increment"></generator>

这种策略的好处:

由于ID自增长的值由程序生成,忽略了各种数据库ID自增长的差异,所以兼容性好

坏处:

因为每次增加一个ID值,都需要调用max()函数,效率不高。

应用场景:

  1. 是用在一些需要支持多种数据库的产品型项目。!!

    1. identity策略(只能用于有 ID 自增长类型的数据库 如  mysql sqlserver ,对不支持自增长策略的数据库  如  oracle db2)在配置前  一定要设置相应表格的  id 自增长

这种策略的好处:效率高。因为直接认为数据库就是使用ID自增长的!!

缺点:兼容性差,只支持有ID自增长的数据库。

  1. native 策略

根据数据库的本地策略生成主键值,如果数据库支持ID自增长策略的,使用ID自增长。如果数据库使用的是序列来生成ID值的,那么就是序列!!

--native效率高于increment,低于identity和sequence.由于不上不下的效率,使用不多!

  1. uuid 策略(注意  对应的字段必须为字符串)

所谓的uuid就是一个唯一的字符串。一般是32位。

那么什么时候使用UUID呢?

应用场景:
有几个开发人员同时开发一个项目。前提每个开发人员使用的都是自己电脑的数据库。
如果使用 ID 自增长作为 ID 列的值,就会导致每个人的数据的 ID 冲突。
但是如果大家使用 UUID。那么冲突的概率,极小

UUID 用于存储基础数据的表。所谓的基础数据,就是系统必须依赖的数据。

  1. assigned策略

HIbernate不使用任何的数据库策略,由调用方手工输入。

手工输入使用的概率不多。一般使用手工输入ID的策略用于一对一的情况

  1. sequence

序列策略:一般用于有序列的数据库。如果像MySQL数据库这种没有序列的数据库使用sequence策略,会使用的一个表来模拟序列。ID值生成规则存放在这个模拟表里面!

  1. 实体类状态转换(难点) 会获得持久态对象

实体类(持久化类)对象是有状态的。
为什么实体类对象会有状态?
答:由于 HIbernate 框架是一个先映射,后操作的框架。所谓的状态就是实体类的对象和数据库是否
有关联的情况。

男孩比作一个对象

女孩子比作一个数据库对象

Hibernate 的持久化类有三种状态:
1. 瞬时态(自由态):与数据库的表没有任何关联关系的实体对象

Customer customer=new Customer();

2. 持久态:正在与数据库保持连接的关系。

Customer customer=session.get(Customer.class,2L);
3. 游离态:曾经被 session 操作过,但 session 失效了。关闭,清除

  1. 瞬时态:

Customer c=new Customer();

    1. 持久态:
  1. 创建的对象被 sesssion 操作过了 ,操作不包括删除!!

@Test

public void save(){

//1.获得数据库的操作对象,session

Session session = HibernateUtils.getSession();

//2.Hibernate默认必须先启动事务,才可以操作(增删改)

Transaction transaction = session.beginTransaction();

//3.封装一个有数据的实体类对象

Customer c=new Customer();

c.setCustName("阿里巴巴");

//4.保存

session.save(c);

//5.提交

transaction.commit();

//这个时候 c,被 session 操作过了。就和数据库建立关系。

//6.关闭

session.close();

}

  1. 游离态: 创建的对象被 sesssion 操作过了,session 关闭了。

瞬时态和游离态,这个两个状态都是和数据库没有关联了。他们区别是:是否曾经被操作过!!

对象状态转移图如下:

注意:根据状态转移图,我们学会如何获得持久态对象就可以(会使用get方法就可以了)了!!!

为什么需要了解如何获得持久态对象呢?

答:因为持久态对象是正在和数据库关联的状态的对象。所以支持以下数据库的操作。

  1. 快照机制支持
  2. 缓存机制的支持
  3. 导航查询的支持。
  1. 一级缓存

HIbernate 的持久态对象是支持一级缓存。所谓的一级缓存就是 Session 级别的缓存。
意思就是说,同一个 session 查询同样的数据,只查询一次数据库。如果出现同多次同样的查询(get/load)
直接返回缓存的数据

问题:如何清除一级缓存?

答:关闭session。和清空session。

. session.close()  session.clear()

注意,close,clear,evit 清空缓存只是将持久态转成游离态,清空的是数据和数据库的关联,而不是清空数据。对象的属性和数据依然存在.

清除缓存的应用场景:秒杀,团购。遇到数据的数据不断更新,而查询的session又不能不断关闭。所以每次查询数据库表之前,需要清空清除一个缓存!!

  1. 快照机制

当对象变成持久态对象(调用get方法时候)的时候,和数据库表关联后。在 session 中会保存两份数据的副本
一份是缓存,一个是快照。
缓存的作用:用于提高查询的效率
快照的作用:用于更新数据,作对比使用。
快照的支持就是持久态对象直接可以通过修改属性更新数据,不需要 update 方法

这里修改持久态对象的属性  直接对该对象数据库中的信息进行更新.

@Test

public void update() {

// 1.获得数据库的操作对象,session

Session session = HibernateUtils.getSession();

//2.更新需要启动事务

Transaction transaction = session.beginTransaction();

//获得持久态对象

Customer customer = session.get(Customer.class, 1L);

//修改属性

customer.setCustName("alibaba");

//提交

transaction.commit();

// .关闭

session.close();

}

执行流程图:

  1. 线程绑定(比进程更小的运行单位)  web项目理解为多线程  每一次请求都是一个线程(Session绑定)

所谓的线程绑定,就是将session的对象绑定到当前的线程变量里面。这样确保了在同一条线程中使用的session对象是相同的!!!

为什么需要线程绑定呢?

答:如果不使用线程绑定,要处理同时对数据库两个操作的业务,需要通过参数传递的方式来确保session的唯一的。

为什么同时操作两个业务的需求,需要session唯一呢?

答:因为数据库事务处理的前提,必须是同一个连接(同一个session)

实现线程绑定的方式:

方式一:

  1. 使用HIbernate的内置实现

Hibernate框架内置支持将对象绑定到当前线程

<property name="hibernate.current_session_context_class">thread</property>

这个时候获得  session 的时候不能够使用  openSession() 方法  要使用 getCurrentSession()方法  获得当前Session 对象.

注意标注红色字体部分.

public class HibernateUtils {

//通过一个静态变量,确保整个项目里面只有一个SessionFactory对象

//为什么建议一个项目只有一个SessionFactory对象?

//答:如果一个项目有多个连接池,可以导致事务不同步!!!

public static SessionFactory sessionFactory=HibernateUtils.createSessionFactory();

//获得会话工厂

private static SessionFactory createSessionFactory(){

//1.获得Configuration对象

Configuration config=new Configuration();

//2.读取配置文件,默认读取的就是classpath根目录的hibernate.cfg.xml

config.configure();

//3.构建会话工厂

SessionFactory sessionFactory = config.buildSessionFactory();

return sessionFactory;

}

//获得会话,就是一个操作对象

public static Session getSession(){

//1.每次都需要在当前线程获得session对象

//注意:getCurrentSession必须要先配置线程绑定才可以使用

return sessionFactory.getCurrentSession();

}

//测试

public static void main(String[] args) {

System.out.println(HibernateUtils.getSession());

}

}

注意事项:

//注意:hibernate内置实现的线程绑定,已经实现随线程启动而启动,随线程关闭而关闭,所以session不能手工关闭

//session.close();

//注意:实现了内置线程绑定后,必须要先启动事务,才可以查询。所以增删改查都需要开启事务!!!

  1. 第二:使用自定义的方式实现 线程绑定.实现代码:

public class HibernateUtils {

//通过一个静态变量,确保整个项目里面只有一个SessionFactory对象

//为什么建议一个项目只有一个SessionFactory对象?

//答:如果一个项目有多个连接池,可以导致事务不同步!!!

public static SessionFactory sessionFactory=HibernateUtils.createSessionFactory();

//声明一个线程变量,作用就是确保存在在线程变量里面的对象,同一条线程是相同的。

private static ThreadLocal<Session> threadLocal=new ThreadLocal<>();

//获得会话工厂

private static SessionFactory createSessionFactory(){

//1.获得Configuration对象

Configuration config=new Configuration();

//2.读取配置文件,默认读取的就是classpath根目录的hibernate.cfg.xml

config.configure();

//3.构建会话工厂

SessionFactory sessionFactory = config.buildSessionFactory();

return sessionFactory;

}

//获得会话,就是一个操作对象

public static Session getSession(){

//判断,线程变量是否存在session

if(threadLocal.get()==null){

Session session = sessionFactory.openSession();

//将session对象放在线程变量里面

threadLocal.set(session);

}

return threadLocal.get();

}

//实现一个关闭的方法,在关闭session后,要移除线程变量里面的session对象

public static void closeSession(){

if(threadLocal.get()!=null){

Session session = threadLocal.get();

//关闭只是session和数据库断开了,但对象还在!!

session.close();

//关闭session后,必须要将线程变量里面的session移除

threadLocal.remove();

}

}

  1. Hibernate查询 API:  get(类字节码,id)

    1. QBC查询:Query By Criteria。(通过Criteria查询API查询)

      1. 示例代码(查询所有客户):

//需求:查询所有的客户,使用Criteria实现

@Test

public void findAll(){

//1.获得操作对象,session

Session session = HibernateUtils.getSession();

//2.获得Criteria查询对象

Criteria criteria = session.createCriteria(Customer.class);

//3.通过criteria对象,查询数据,返回多条数据,使用list

List<Customer> customers = criteria.list();

for(Customer c:customers){

System.out.println(c.getCustName());

}

session.close();

}

  1. 模糊查询:

/**

* 需求:查询客户名有"百"的客户

*/

@Test

public void findByName(){

//1.获得操作对象,session

Session session = HibernateUtils.getSession();

//2.获得Criteria查询对象

Criteria criteria = session.createCriteria(Customer.class);

//设置条件

criteria.add(Restrictions.like("custName", "%百%"));

//3.通过criteria对象,查询数据,返回多条数据,使用list

List<Customer> customers = criteria.list();

for(Customer c:customers){

System.out.println(c.getCustName());

}

session.close();

}

  1. 分页查询:

//需求:查询第 3 条开始,取 4 条件数据

@Test

public void findByPage(){

//1.获得操作对象,session

Session session = HibernateUtils.getSession();

//2.获得Criteria查询对象

Criteria criteria = session.createCriteria(Customer.class);

//设置分页

//(1)设置开始的位置,开始位置从0开始,第三条数据的下标为2

criteria.setFirstResult(2);

//(2)设置每页的记录数,每页返回的数据时4条,设置为4

criteria.setMaxResults(4);

//3.通过criteria对象,查询数据,返回多条数据,使用list

List<Customer> customers = criteria.list();

for(Customer c:customers){

System.out.println(c.getCustName());

  1. HQL查询(实际开发中较常用)

    1. Hql(hibernate query language)查询所有客户:

package com.bdqn.test;

import java.util.List;

import org.hibernate.Query;

import org.hibernate.Session;

import org.junit.Test;

import com.bdqn.entity.Customer;

import com.bdqn.utils.HibernateUtils;

public class CustomerDAOTest {

// 需求:查询所有的客户,使用hql实现

@Test

public void findAll() {

// 1.获得操作对象,session

Session session = HibernateUtils.getSession();

// 2.获得hql查询对象

Query query = session.createQuery("from Customer");

// 3.通过criteria对象,查询数据,返回多条数据,使用list

List<Customer> customers = query.list();

for (Customer c : customers) {

System.out.println(c.getCustName());

}

session.close();

}

@Test

public void findAll1() {

// 1.获得操作对象,session

Session session = HibernateUtils.getSession();

// 2.获得hql查询对象

// 注意,select返回不能是*,必须是一个属性或者对象的别名

Query query = session.createQuery("select c from Customer c");

// 3.通过criteria对象,查询数据,返回多条数据,使用list

List<Customer> customers = query.list();

for (Customer c : customers) {

System.out.println(c.getCustName());

}

session.close();

}

  1. Hql模糊查询

/**

* 需求:查询客户名有"百"的客户

*/

@Test

public void findByName() {

// 1.获得操作对象,session

Session session = HibernateUtils.getSession();

// 2.获得Criteria查询对象

Query query = session.createQuery("from Customer c where c.custName like ?");

// 设置条件,注意,设置的下标0,为hql的第一个?的值

query.setString(0, "%百%");

// 3.通过criteria对象,查询数据,返回多条数据,使用list

List<Customer> customers = query.list();

for (Customer c : customers) {

System.out.println(c.getCustName());

}

session.close();

}

  1. Hql分页查询:

// 需求:查询第 3 条开始,取 4 条件数据

@Test

public void findByPage() {

// 1.获得操作对象,session

Session session = HibernateUtils.getSession();

// 2.获得hql查询对象

Query query = session.createQuery("from Customer");

// 设置分页条件

// (1)设置开始位置,从0开始,第三条数据下标为2

query.setFirstResult(2);

// (2)设置每页的记录数据,为4

query.setMaxResults(4);

// 3.通过criteria对象,查询数据,返回多条数据,使用list

List<Customer> customers = query.list();

for (Customer c : customers) {

System.out.println(c.getCustName());

}

session.close();

}

  1. Hql查询总记录:

// 需求:统计记录数据

@Test

public void count() {

// 1.获得操作对象,session

Session session = HibernateUtils.getSession();

// 2.获得hql查询对象

// 注意,select返回不能是*,必须是一个属性或者对象的别名

Query query = session.createQuery("select count(c) from Customer c");

// 3.返回一条数据,使用uniqueResult

// 注意:如果返回的数据不确定,随便设置一个类型让它报错。通过错误信息分析返回的类型

Long uniqueResult = (Long) query.uniqueResult();

System.out.println(uniqueResult);

session.close();

}

  1. Hql:投影查询(查询部分属性)  了解

// 需求:查询客户的信息,返回custName和custSource

@SuppressWarnings("unchecked")

@Test

public void findAll2() {

// 1.获得操作对象,session

Session session = HibernateUtils.getSession();

// 2.获得hql查询对象

// 注意,select返回不能是*,必须是一个属性或者对象的别名

Query query = session.createQuery("select c.custName,c.custSource from Customer c");

// 3.通过criteria对象,查询数据,返回多条数据,使用list

List<Object[]> customers = query.list();

for (Object[] object : customers) {

System.out.println("客户名:" + object[0] + ",客户来源:" + object[1]);

}

session.close();

}

// 需求:查询客户的信息,返回custName和custSource,但是必须使用一个customer对象接收

/**

*

* 当查询的记录不是所有字段。而是指定的字段。

* 如果需要使用一个实体类接收。那么需要一个有参数的构造方法。我们将这种,有构造方法参数的查询,称为投影查询

*/

@Test

public void findAll3() {

// 1.获得操作对象,session

Session session = HibernateUtils.getSession();

// 2.获得hql查询对象

// 注意,select返回不能是*,必须是一个属性或者对象的别名

Query query = session.createQuery("select new Customer(c.custName,c.custSource) from Customer c");

// 3.通过criteria对象,查询数据,返回多条数据,使用list

List<Customer> customers = query.list();

for (Customer c : customers) {

System.out.println("客户名:" + c.getCustName() + ",客户来源:" + c.getCustSource());

}

session.close();

}

}

  1. HQL操作

所谓的HQL操作,就是使用HQL实现数据库的删改。

  1. Hql删除:

注意:HQL是不支持增加的!!!

public class CustomerDAOTest {

//需求:删除客户名有"百"的客户

@Test

public void delete(){

//1.获得操作对象

Session session = HibernateUtils.getSession();

//2.操作需要开启事务

Transaction transaction = session.beginTransaction();

//3.获得hql操作对象

Query query = session.createQuery("delete from Customer c where c.custName like ?");

//4.设置删除的条件

query.setString(0, "%百%");

//5.执行hql,返回的是影响行数

int count = query.executeUpdate();

System.out.println(count);

transaction.commit();

session.close();

}

//需求:删除客户名有"百"的客户,使用命名参数实现

//所谓的命名参数,就是使用一个自定义的名字代替原来的?

@Test

public void delete1(){

//1.获得操作对象

Session session = HibernateUtils.getSession();

//2.操作需要开启事务

Transaction transaction = session.beginTransaction();

//3.获得hql操作对象

//注意:命名参数声明的时候,使用有 :(冒号的)

Query query = session.createQuery("delete from Customer c where c.custName like :custName");

//4.设置删除的条件,设置条件的时候,命名参数是没有冒号的

query.setString("custName", "%小%");

//5.执行hql,返回的是影响行数

int count = query.executeUpdate();

System.out.println(count);

transaction.commit();

session.close();

}

}

  1. Hql更新:

//需求:通过hql实现,更新客户名名,有“百”的客户来源,为互联网

@Test

public void update(){

//1.获得操作对象

Session session = HibernateUtils.getSession();

//2.操作需要开启事务

Transaction transaction = session.beginTransaction();

//3.获得hql操作对象

//注意:命名参数声明的时候,使用有 :(冒号的)

Query query = session.createQuery("update Customer c set c.custSource = ? where c.custName like  ?");

//4.设置删除的条件,设置条件的时候,命名参数是没有冒号的

query.setString(0, "互联网");

query.setString(1, "%百%");

//5.执行hql,返回的是影响行数

int count = query.executeUpdate();

System.out.println(count);

transaction.commit();

session.close();

}

相对于SQL,使用HQL的好处是什么?

答:HQL操作的是对象,不是数据库的表。所以所有的数据库的语法是一样的。屏蔽了不同数据库的方言的差异!!!!

由于Criteria查找接口比较笨重,所以建议使用HQL。

  1. 总结

1今天学习了各种HIbernate的组件。

ID生成策略

  1. identity

必须要知道如何获得持久态对象。

  1. 通过查询可以获得  get(类字节码,id)
  2. 可以通过更新获得   update(object)
  3. 可以通过插入获得   save(object)

持久态对象有什么用

  1. 支持缓存
  2. 支持快照
  3. 支持导航查询

线程绑定:目的是为了不用传递参数,在同一条线程操作上,任何位置获得的session是相同的。

为什么有这个需求

原因因为事务处理必须是同一个session才可以实现!!!!!

三种实现线程绑定的方式,会内置配置方式和自定义配置方式。

查找的API。

使用Criteria查找接口。就是使用纯Java对象。查询数据库。(了解)

使用HQL查询接口,通过HQL实现数据库的操作(重点)

相对于SQL,使用HQL的好处是什么?

答:HQL操作的是对象,不是数据库的表。所以所有的数据库的语法是一样的。屏蔽了不同数据库的方言的差异!!!!

Hibernate QBC查询相关推荐

  1. Hibernate 学习笔记(二)—— Hibernate HQL查询和 QBC 查询

    目录 一.Hibernate 的 HQL 查询 1.1.查询所有数据 1.2.条件查询 1.3.排序查询 1.4.统计查询 1.5.分页查询 1.6.投影查询 二.Hibernate 的 QBC 查询 ...

  2. Hibernate的集中查询方式 : hql查询,QBC查询和QBE查询

    转载:http://blog.csdn.net/iijse/article/details/6161143 通常使用的Hibernate通常是三种:hql查询,QBC查询和QBE查询:  1.QBE( ...

  3. Hibernate学习之路(十三):Hibernate中的QBC查询和本地sql操作

    什么是hibernate的QBC查询 QBC 查询就是通过使用 Hibernate 提供的 Query By Criteria API 来查询对象,这种 API 封装了 SQL 语句的动态拼装,对查询 ...

  4. Hibernate通常是三种:hql查询,QBC查询和QBE查询:

    一:Hibernate QBC与HQL优缺点 QBC 全称:Query By Criteria HQL 全称:hibernate Query Language HQL优点:与sql相近,可读性好,功能 ...

  5. Hibernate中的QBC查询方式详解

    Hibernate中的QBC查询方式详解 QBC:Query By Criteria,条件查询. 是一种更加面向对象化的查询的方式. 1.QBC简单查询 测试代码: package com.pipi. ...

  6. Hibernate框架--学习笔记(下):hibernate的查询方式、多表查询、检索策略、批量抓取

    一.hibernate的查询方式: 主要有五种:对象导航查询:OID查询:hql查询:QBC查询:本地sql查询. 1.对象导航查询:根据id查询某个客户,再查询这个客户里面所有的联系人. 2.OID ...

  7. hibernate的查询方式

    hibernate的查询方式常见的主要分为三种: HQL, QBC(Query By Criteria)查询, 以及使用原生SQL查询 HQL查询 • HQL(Hibernate Query Lang ...

  8. Hibernate各种查询方法

    1 hibernate的查询方式 2 对象导航查询 3 hql查询 (1)查询所有 (2)条件查询 (3)排序查询 (4)分页查询 (5)投影查询 (6)聚集函数使用 4 qbc查询 (1)查询所有 ...

  9. hibernate QBC和QBE精讲与案列分析(上)

    转载:http://blog.sina.com.cn/s/blog_7fff746d0101ese2.html 本章的主要内容包括: ● QBC数据检索 ● 连接查询 ● Hibernate的数据检索 ...

最新文章

  1. 全国大学生智能汽车竞赛-讯飞智慧餐厅
  2. OBJECT_METHOD初窥
  3. python如何删除文件夹下文件和文件夹?
  4. 08年最热门七大技术和最紧缺的IT人才
  5. swiper默认选中_Swiper
  6. GitHub网站使用的基础入门
  7. python中response对象的属性_Django 中的响应对象 Response
  8. 使用Zookeeper实现负载均衡原理
  9. 论文赏析[EACL17]K-best Iterative Viterbi Parsing(K-best迭代维特比句法分析)
  10. NetBeans在Apache基金会取得的进展
  11. stopwords怎么用_【技术】怎么用Python画出好看的词云图?
  12. 详解全局免流原理(转载)
  13. java图书管理系统的简单实现
  14. 又一北京“假名媛”曝光,蹭吃蹭喝21天,暴露人性最真实一面
  15. 2021-08-18 关于PC与ipad的远程控制
  16. p3.第一章 Python基础入门 -- Python编程基本概念 (三)
  17. win8计算机的录音功能,win8电脑录音机功能在哪|win8录音功能使用方法
  18. CSDN什么时候倒闭啊
  19. 哈工大软件构造第一章总结
  20. ue4 android联机,UE4 局域网联机(LAN)

热门文章

  1. 父类引用指向子类对象的方法调用问题
  2. 谷歌浏览器被hao123劫持
  3. 指数基金(三):指数基金估值指标
  4. TensorFlow中简单的LSTM代码实现
  5. 揭密玄学奥秘(一):风水, 姓名八字其实都是科学...
  6. 华宇(大连)二面-20190620
  7. PTE岗位实习期第二次考核
  8. 记一次WebLogic10 PermGen space解决方法
  9. rust自我解脱_失恋后安慰的话 自我解脱
  10. python sched_python定时任务-sched模块