hibernate

来源:互联网 发布:计算机就业前景 知乎 编辑:程序博客网 时间:2024/06/02 02:28
Hibernate

ORM介绍

1.Hibernate框架的作用:

-- 能让程序员以面向对象的方式来操作数据库,从而简化持久层的开发。

-- 它底层可以跨数据库. (程序人员开发项目不用关心项目用得是什么数据库).

2.ORM:Object Relation Mapping 对象关系映射.

-- Object: 对象指得是面向对象的编程语言.

-- Relation: 关系指得是关系型数据库.

-- Mapping: 面向对象的编程语言与关系型数据库之间的映射.

3.ORM思想:它是用来解决面向对象的编程语言与关系型数据库之间的映射.

-- ORM它只是一种思想,不是指具体的某个框架.

-- ORM框架:Hibernate5、TopLink、JDO等.

MVC: Model View Controller 它也是一种思想,不是指具体的某个框架.

具体实现框架: webwork、Struts1、Struts2、SpringMVC.

4.JPA:Java Persistence Api (java持久化api).

-- JPA 与 ORM 之间的关系:

JPA是sun公司根据ORM思想制订出来的持久化层的规范.(提供了一套标准的持久化api)


JDBC: Java DataBase Connection java数据库连接的规范.

JDBC它是sun为各个数据库厂商制订的连接数据库的规范.(提供了一套标准的数据库连接api).


-- JPA的实现商:Hibernate、TopLink、JDO等.

由于JPA出现的时间比Hibernate晚,所以我们既要学习Hiberante框架,又要学习JPA.

目前企业一般用JPA的注解来写持久化类,所以我们只学习JPA注解持久化类部分的内容。

5.ORM映射思想:

面向对象的编程语言(java) 关系型数据库

类 表

对象 一行数据

属性 列名

Hibernate介绍

Hibernate是目前最流行的ORM框架,同时也是JPA的实现商。

框架下载:

-- 它的官方网站:http://www.hibernate.org

-- Hibernate5最新版本:5.*.Final

-- 它属于Jboss公司的产品.

-- 下载hibernate-release-5.*.Final.zip压缩包.

hibernate目录结构

-- documentation : 全部的文档

-- mappingGuide : 映射指南.

-- javadocs : api文档.

-- userGuide : 用户指南.

-- quickstart : 快速开始.

-- lib: 存放了所有的jar(第三方的、自己的).

-- required : 必须要的jar.

-- jpa : jpa实现的jar.

-- optional: 可选的.

-- c3p0 : 连接池(现在企业用得最多的连接池).

-- ehcache : 缓存框架.

-- proxool : 连接池.

-- project : 存放了Hibernate框架的源码、测试用例、资源文件、示例.

-- project/etc : 存放了配置文件的模版.

快速入门

第一步:拷贝jar

-- lib\required\所有jar包

-- lib\jpa\所有jar包

-- lib\optional\c3p0\所有jar包

-- mysql驱动

注意:hibernate5已经支持JDK8的,但也兼容JDK6

如果需要使用JDK8,需要配套添加hibernate_java8.jar即可

第二步:写全局的配置文件.

src/hibernate.cfg.xml

cfg: configuration

第三步:写持久化类(普通的javaBean + jpa注解)

第四步:hibernate编程

-- Configuration

-- SessionFactory

-- Session

-- Transaction

环境搭建(基于XML方式)

导入jar包

lib\required\所有jar包

-- antlr-2.7.7.jar

-- dom4j-1.6.1.jar

-- geronimo-jta_1.1_spec-1.1.1.jar

-- hibernate-commons-annotations-5.*.Final.jar

-- hibernate-core-5.*.Final.jar

-- hibernate-jpa-2.1-api-1.0.0.Final.jar

-- jandex-1.2.2.Final.jar

-- javassist-3.18.1-GA.jar

-- jboss-logging-3.3.0.Final.jar

lib\jpa\所有jar包

-- hibernate-entitymanager-5.*.Final.jar

lib\optional\c3p0\所有jar包

-- c3p0-0.9.2.1.jar

-- hibernate-c3p0-5.*.Final.jar

-- mchange-commons-java-0.2.3.4.jar

注意:hibernate5已经支持JDK8的,但也兼容JDK6

如果需要使用JDK8,需要配套添加lib\java8\hibernate-java8-5.*.Final.jar即可

mysql驱动

-- mysql-connector-java-5.1.37.jar

配置hibernate.cfg.xml文件

该配置文件可以参考:

-- project\etc\hibernate.cfg.xml

-- project\etc\hibernate.properties (全局属性配置模版)

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>

<!-- 数据库方言(告诉Hibernate4项目用到是什么数据库)

如果使用的mysql5数据库版本在5.5之后的话,方言通常建议使用MySQL5InnoDBDialect

MySQLDialect 不支持事务

MySQLInnoDBDialect 支持事务

-->

<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>

<!-- 配置是否支持自动创建表(不要指望Hibernate创建数据库)

create-drop 在创建SessionFatory时候就会自动创建数据库表,当SessionFatory关闭的时候会将创建的表删除

create 每次创建SessionFactory时先删除上次创建的数据库中表,然后再创建对应数据库表。

update 每次创建SessionFactory时先检查是否已有数据库表,如果没有表就会自动创建表,

如果有表就会修改的表,但是不会影响原来的数据 (通常用这个)

validate 每次创建SessionFactory的时候会验证表结构。

-->

<property name="hibernate.hbm2ddl.auto">update</property>

<!-- 显示SQL语句 -->

<property name="hibernate.show_sql">true</property>

<!-- 格式化SQL语句(配置了show_sql属性才生效) -->

<property name="hibernate.format_sql">true</property>

<!-- 数据库驱动 -->

<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>

<!-- 连接数据库url-->

<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate_db</property>

<!-- 连接数据库用户名 -->

<property name="hibernate.connection.username">root</property>

<!-- 连接数据库密码 -->

<property name="hibernate.connection.password">root</property>

<!-- 配置最大连接数 -->

<property name="hibernate.c3p0.max_size">10</property>

<!-- 配置最小连接数 -->

<property name="hibernate.c3p0.min_size">2</property>

<!-- 配置持久化类 -->

<mapping class="com.yayadou.domain.Person"/>

<mapping resource="com/yayadou/domain/User.hbm.xml"/>

</session-factory>

</hibernate-configuration>

写持久化的类

持久化类 = pojo + xxx.hbm.xml.(旧的方式)

持久化类 = pojo + annotation注解. (@Entity)

普通的pojo+User.hbm.xml

pojo: Plain Old Java Object 最简单最传统的java对象.

写pojo类时要注意下面四点:

-- 必须有一个无参的构造器.

-- 所有的属性必须有setter与getter方法.

-- 所有的属性不能用final修饰.

-- 必须有一个唯一的标识属性.(生成表中的主键列).

xxx.hbm.xml文件模版位置:

hibernate-release-5.*.Final\project\hibernate-core\src\test\resources\org\hibernate\test\annotations\Boat.hbm.xml.

User类

package com.yayadou.domain;

/**

* User

*/

public class User {

private Integer id;

private String name;

private String phone;

/** setter and getter method */

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 String getPhone() {

return phone;

}

public void setPhone(String phone) {

this.phone = phone;

}

}

user.hbm.xml

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC

"-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.yayadou.domain">

<class name="User" table="t_user">

<!-- id属性作为表的主键列,列名为user_id -->

<id name="id" column="user_id">

<!-- 指定主键生成策略 native指定让hibernate5根据方言自己选择数据库相关生成器-->

<generator class="native"/>

</id>

<!-- name属性作为表中的user_name列 -->

<property name="name" column="user_name"/>

<!-- phone属性作为表中的user_phone列 -->

<property name="phone" column="user_phone"/>

</class>

</hibernate-mapping>

写测试类

开发步骤:

1.创建Configuration配置信息对象

2.创建SessionFactory

3.获取Session

4.开启事务Transaction

5.调用Session的方法完成所有的持久化操作

6.事务提交commit()或回滚rollback()

7.关闭Session与SessionFactory

UserTest原来的方式

public static void main(String[] args) {

//1:创建Configuration

Configuration configuration = new Configuration() // 加载hibernate.properties

.configure(); // 加载hibernate.cfg.xml

//2:创建SessionFactory (它底层封装了数据源DataSource)

SessionFactory sessionFactory = configuration.buildSessionFactory();

//3:创建Session (它底层封装了数据库连接Connection)

Session session = sessionFactory.openSession();

//4:开启事务得到事务对象

Transaction t = session.beginTransaction();

User u = new User();

u.setName("hanfeili");

u.setPhone("13688888888");

//5 将对象u保存到数据库表中

session.save(u);

//6.事务提交commit()或回滚rollback()

t.commit();

//7.关闭session与SessionFactory

session.close();

sessionFactory.close();

}

UserTest类

package com.yayadou.test;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.Transaction;

import org.hibernate.boot.registry.StandardServiceRegistryBuilder;

import org.hibernate.cfg.Configuration;

import org.hibernate.service.ServiceRegistry;

import com.yayadou.domain.User;

/**

* UserTest

*/

public class UserTest {

public static void main(String[] args) throws Exception {

/** 第一步:创建Configuration */

Configuration configuration = new Configuration() // 默认加载hibernate.properties属性文件

.configure(); // 默认加载hibernate.cfg.xml文件

//配置需要加载操作的类

configuration.addClass(User.class);

/** 第二步:创建注册服务对象 */

ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()

.applySettings(configuration.getProperties()).build();

/** 第三步:创建SessionFactory */

SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);

/** 第四步:获取Session */

Session session = sessionFactory.openSession();

/** 第五步:开启事务,获取事务对象 */

Transaction transaction = session.beginTransaction();

/** 第六步:调用Session的方法完成所有的持久化操作 */

User u = new User();

u.setName("hanfeili");

u.setPhone("13688888888");

// 将对象u保存到数据库表中

session.save(u);

/** 第七步:事务提交commit()或回滚rollback() */

transaction.commit();

/** 第八步:关闭Session与SessionFactory */

session.close();

sessionFactory.close();

}

}

环境搭建(基于annotation方式)

写测试类

开发步骤:

1.创建Configuration配置信息对象

2.创建SessionFactory

3.获取Session

4.开启事务Transaction

5.调用Session的方法完成所有的持久化操作

6.事务提交commit()或回滚rollback()

7.关闭Session与SessionFacto

personTest类

package com.yayadou.test;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.Transaction;

import org.hibernate.boot.registry.StandardServiceRegistryBuilder;

import org.hibernate.cfg.Configuration;

import org.hibernate.service.ServiceRegistry;

import com.yayadou.domain.Person;

/**

* PersonTest

*/

public class PersonTest {

public static void main(String[] args) throws Exception {

/** 第一步:创建Configuration */

Configuration configuration = new Configuration() // 默认加载hibernate.properties属性文件

.configure(); // 默认加载hibernate.cfg.xml文件

/** 第二步:创建注册服务对象 */

ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()

.applySettings(configuration.getProperties()).build();

/** 第三步:创建SessionFactory */

SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);

/** 第四步:获取Session */

Session session = sessionFactory.openSession();

/** 第五步:开启事务,获取事务对象 */

Transaction transaction = session.beginTransaction();

/** 第六步:调用Session的方法完成所有的持久化操作 */

Person p = new Person();

p.setId(1);

p.setAge(20);

p.setName("hanfeili");

// 将对象p保存到数据库表中

session.save(p);

/** 第七步:事务提交commit()或回滚rollback() */

transaction.commit();

/** 第八步:关闭Session与SessionFactory */

session.close();

sessionFactory.close();

}

}

写持久化的类

持久化类 = pojo + xxx.hbm.xml.(旧的方式)

持久化类 = pojo + annotation注解. (@Entity)

普通pojo+annotation注解

pojo: Plain Old Java Object 最简单最传统的java对象.

写pojo类时要注意下面四点:

-- 必须有一个无参的构造器.

-- 所有的属性必须有setter与getter方法.

-- 所有的属性不能用final修饰.

-- 必须有一个唯一的标识属性. @Id (生成表中的主键列).

annotation注解:

-- @Entity

-- @Id

Person类

package com.yayadou.domain;

import javax.persistence.Entity;

import javax.persistence.Id;

/**

* Person

*/

@Entity

public class Person {

@Id

private Integer id;

private String name;

private int age;

public Person(){

}

/** setter and getter method */

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 int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

}

Hibernate核心API说明

Configuration

Configuration: 专门负责加载全局的配置文件,产生SessionFactory。

创建Configuration对象代码如下:

Configuration cfg = new Configuration() // 默认加载src目录下hibernate.properties属性文件

.configure(); // 默认加载src目录下hibernate.cfg.xml配置文件

Session(会话)

Session: 它是应用程序与持久层进行交互的单线程对象。

-- 它是线程不安全。

-- 它存活的时间比较短.(因为它底层封装得是Connection,用完就要关闭).

-- 它是事务工厂.

-- 有一个必须开启的一级缓存. (一级缓存永远都是开启的).

Session : 会话(持续的一段有效的时间).

HttpSession: 浏览器打开到浏览器关闭.

SqlSession: 数据库连接的获取到数据库连接的关闭.

Session: 数据库连接的获取到数据库连接的关闭.

调用代码

Session session = sessionFactory.openSession();

SessionFactory

SessionFactory:它是当前数据库在内存中镜像。一个SessionFactory对应一个数据库,所以一个Web应用只需要一个SessionFactory即可,

当Web应用启动时就获取SessionFactory,当Web应用关闭时才关闭SessionFactory.

-- 它是线程安全的.

-- 它是创建Session的工厂.

-- 它底层封装了数据源(连接池).

-- 它有一个可选的二级缓存.(默认是关闭的).

调用代码:

SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);

Transaction(事物)

Transaction: Hibernate事务对象.

-- JDBC事务(局部事务): 只能对一个数据库中的表做事务. (web容器) tomcat jetty

-- JTA事务(全局事务、分布式事务): 可以对多个数据库中的表做事务.(EJB容器)

WebSphere(IBM)、WebLogic(Oracle)、JBoss(jboss)

调用代码:

Transaction tx = session.beginTransaction();

增、删、改

tx.commit();

注:使用Hibernate进行操作时(增、删、改)必须显示的调用Transaction(默认:autoCommit=false)。

ConnectionProvider

ConnectionProvider: 数据库连接的提供者,一般指得是数据源DataSource(连接池

全局配置文件

hibernate.cfg.xml

1.数据库方言:

hibernate.dialect : org.hibernate.dialect.MySQL5InnoDBDialect

2.是否显示SQL语句:

hibernate.show_sql : true|false

3.是否格式化SQL语句:

hibernate.format_sql : true|false

4.配置是否支持自动创建表:

hibernate.hbm2ddl.auto: create_drop|create|update|validate

5.数据库连接的信息:

hibernate.connection.driver_class : 数据库驱动类

hibernate.connection.url : 连接数据库URL

hibernate.connection.username : 连接数据库用户名

hibernate.connection.password : 连接数据库密码

6.c3p0连接池的信息:

hibernate.c3p0.max_size : 最大连接数

hibernate.c3p0.min_size : 最小连接数

7.配置持久化类:

<mapping class="com.yayadou.domain.Person"/>

<mapping resource="com/yayadou/domain/User.hbm.xml"/>

hibernate.properties+持久化类

#-- 配置数据库方言,告诉Hibernate4我们用得是什么样的数据库

hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect

#-- 配置显示SQL语句

hibernate.show_sql=true

#-- 配置格式化SQL语句

hibernate.format_sql=true

#-- 配置是否支持自动创建表:

# create-drop: 当创建SessionFactory时就会创建表、当SessionFactory关闭时就会删除表.

# create: 当创建SessionFactory时先删除表,再创建表 (每次)

# update: 当创建SessionFactory时会判断,如果表不存在就创建表,存在就不会创建表,后面会修改表结构.

# validate : 只做验证(不会创建表) (不需要Hibernate4创建表)

hibernate.hbm2ddl.auto=update

#-- 配置连接数据库的驱动类

hibernate.connection.driver_class=com.mysql.jdbc.Driver

#-- 配置连接数据库的URL (创建数据库)

hibernate.connection.url=jdbc:mysql://localhost:3306/hibernate_db

#-- 配置连接数据库的用户名

hibernate.connection.username=root

#-- 配置连接数据库的密码

hibernate.connection.password=root

#-- 配置c3p0连接池中最大连接数

hibernate.c3p0.max_size=10

#-- 配置c3p0连接池中最小连接数

hibernate.c3p0.min_size=2

添加持久化类

/** 第一步:创建Configuration */

Configuration configuration = new Configuration() // 默认加载hibernate.properties属性文件

.addAnnotatedClass(Person.class) // 添加持久化类

.addAnnotatedClass(Xxx.class); // 添加持久化类

缓存配置文件

ehcache.xml

持久化类配置文件

xxx.hbm.xml

hbm: Hibernate Mapping (Hibernate映射文件)

<!-- package: 包名 -->

<hibernate-mapping package="com.yayadou.domain">

<!-- name:指定类名 table:指定表名 -->

<class name="User" table="USER_INFO">

<!-- 主键列 -->

<id name="id" column="user_id">

<!-- 指定主键生成策略 -->

<generator class="native"/>

</id>

<!-- 属性名转化成表中列名 -->

<property name="name" column="user_name"/>

<!-- 属性名转化成表中列名 -->

<property name="phone" column="user_phone"/>

<property name="属性名" column="表中列名"/>

</class>

</hibernate-mapping>

hibernate体系结构


概览图


完整体系图


持久化对象的状态


持久化类 持久化对象 = new 持久化类();


瞬时状态(Transient)

Transient 瞬态:

new 持久化类(),刚new出来的,从来没有与Session关联过.

也就是没有调用Session的方法对它进行操作过。

持久化(Persistent)

Persistent 持久化状态: 正在被Session管理中。调用Session的方法对它进行操作过,这个时候Session没有关闭.

该对象正在Session一级缓存中.(一级缓存中的对象都是存放在内存中).

如果你调用持久化状态对象的set方法,它会影响数据库表中的数据.

你对持久化状态对象做的修改,会同步到底层的数据库表中,

它不是立即同步到底层的数据库,默认是在事务提交时才同步。

托管(Detached)

Detached 脱管状态:脱离了Session的管理,曾经被Session管理过,现在没有被Session管理。

Session的主要方法

Session的主要方法说明:

1.保存(添加)

-- Serializable save(entity); // entity : 持久化状态

-- void saveOrUpdate(entity); // entity : 持久化状态

-- void persist(entity); // entity : 持久化状态

-- Object obj = merge(entity); // entity : 瞬态,obj : 持久化状态

2.修改

-- void update(entity); // entity : 持久化状态

-- void saveOrUpdate(entity); // entity : 持久化状态

-- Object obj = merge(entity); // entity : 瞬态,obj : 持久化状态

3.删除

-- void delete(entity); // entity : 瞬态

4.根据主键获取实体

-- Object entity = session.get(持久化类, 主键id值); // entity : 持久化状态

-- Object entity = session.load(持久化类, 主键id值); // entity : 持久化状态

1.保存(添加)

-- Serializable save(entity); // entity : 持久化状态

-- void saveOrUpdate(entity); // entity : 持久化状态

-- void persist(entity); // entity : 持久化状态

-- Object obj = merge(entity); // entity : 瞬态,obj : 持久化状态

save()方法:

-- 它会立即往数据库表中插入数据(马上生成insert语句),等到事务提交时数据库表才会有数据。

-- 调用save方法有返回值, 它的返回值是主键id值。

User user = new User(); // user --> 瞬态

user.setAge(18);

user.setName("hanfeili");

user.setPhone("13888888888");

Serializable id = session.save(user); // user --> 持久化状态

persist()方法:

-- 它会延迟往数据库表中插入数据.(在事务没有开启情况下).

-- 调用该方法没有返回值.要想获取主键id值需调用对象的getId()方法.

User user = new User(); // 瞬态

user.setAge(18);

user.setName("hanfeili2");

user.setPhone("13888888886");

session.persist(user); // user --> 持久化状态

// 判断Session的一级缓存中是否包含这个对象,true: 持久化状态

System.out.println(session.contains(user));

saveOrUpdate()方法:

-- 它集成的添加与修改两个功能.

-- 想用该方法做添加,不要设置对象的主键值即可.

User user = new User(); // 瞬态

user.setAge(18);

user.setName("hanfeili3");

user.setPhone("13888888887");

session.saveOrUpdate(user); // user --> 持久化状态

// 判断Session的一级缓存中是否包含这个对象,true: 持久化状态

System.out.println(session.contains(user));

merge()方法:

-- 它混合集成了添加与修改两个操作。

-- 想用该方法做添加,不要设置对象的主键值即可.

User user = new User(); // 瞬态

user.setAge(18);

user.setName("hanfeili4");

user.setPhone("13888888886");

User u = (User)session.merge(user); // u --> 持久化状态

// 判断Session的一级缓存中是否包含这个对象,true: 持久化状态

System.out.println(session.contains(user)); // 瞬态

System.out.println(session.contains(u));// u --> 持久化状态

持久化状态下做修改:

-- 只需要调用该对象的setXxx()方法对实体做修改即可.

-- 对持久化状态对象做的修改,会同步到底层的数据库表中,

它不是立即同步到底层的数据库,默认是在事务提交时才同步.

User user = (User)session.get(User.class, 1); // user : 持久化状态

// 判断Session的一级缓存中是否包含这个对象,true: 持久化状态

System.out.println(session.contains(user));

user.setAge(100);

user.setName("hanfeili");


脱管状态下做修改:

-- 创建持久化类对象设置它的主键值(瞬态转化成脱管).

-- 调用脱管状态下对象的setXxx方法设置属性值.

-- 调用Session的三个方法进行修改(update、saveOrUpdate、merge).

update()方法:

-- 脱管状态下对象做修改.

User u = new User(); // 瞬态

u.setId(1); // 脱管

u.setAge(200);

session.update(u); // u --> 持久化状态

System.out.println(session.contains(u));

saveOrUpdate()方法:

-- 脱管状态下对象做修改.

User u = new User(); // 瞬态

u.setId(1); // 脱管

u.setAge(210);

u.setName("admin");

session.saveOrUpdate(u); // u --> 持久化状态

System.out.println(session.contains(u));

merge()方法:

-- 脱管状态下对象做修改.

User u = new User(); // 瞬态

u.setId(1); // 脱管

u.setAge(210);

u.setName("admin");

User us = (User)session.merge(u); // us --> 持久化状态

System.out.println(session.contains(u)); // u --> 脱管状态

System.out.println(session.contains(us)); // us --> 持久化状态

持久化状态下做删除:

-- 从数据库表中根据主键值获取一个对象(持久化状态对象).

User user = (User)session.get(User.class, 1); // user : 持久化状态

session.delete(user); // user 瞬态

// 判断Session的一级缓存中是否包含这个对象,true: 持久化状态

System.out.println(session.contains(user));

脱管状态下做删除:

-- 创建持久化类对象设置它的主键值(瞬态转化成脱管).

User u = new User(); // u -> 瞬态

u.setId(3); // u -> 脱管

session.delete(u); // 瞬态

根据主键查询单条记录

重点:get和load方法的区别:

get的方法(推荐):

-- get 根据主键id查询一条记录(立即查询)

-- get方法返回的是一个持久化类的实例,立即执行就发起SQL语句查询id对应的记录

-- get方法查询id对应的记录不存在的时候 返回 null

----------------------------------------------------------------------------------------------

load的方法:

-- load 根据主键id查询一条记录(延迟查询).

-- load方法返回的是一个持久化类的代理对象,当真正访问除id以外的属性的时候才去发起SQL语句查询id对应的记录

当你真正用到该代理对象的属性时,有可能出现session关闭的异常,因为要去数据库表中查询,那Session就不能关闭,

因为Session封装了数据库连接.

-- load方法查询id对应的记录不存在的时候报 ObjectNotFoundException 异常.


-- 根据主键id查询一条记录(立即查询).

User user = (User)session.get(User.class, 1); // user : 持久化状态

System.out.println(user.getName() + "==" + user.getAge());

// 判断Session的一级缓存中是否包含这个对象,true: 持久化状态

System.out.println(session.contains(user));


-- 根据主键id查询一条记录(延迟查询).

-- 延迟从数据库表查询数据,一开始返回代理对象,当你真正要用到它的属性时,才会生成查询语句到数据库表中查询数据。

当你要用到它的时候,要保证Session不能关闭。

User user = (User)session.load(User.class, 2); // user : 持久化状态

System.out.println(user.getName() + "==" + user.getAge());

// 判断Session的一级缓存中是否包含这个对象,true: 持久化状态

System.out.println(session.contains(user));

-- 将普通的pojo转化成持久化类.

-- 该注解写在pojo类上.

@Table: 把持久化类转化成表的相关信息。

-- name:指定表名。

-- indexes: 用于指定表的引索列.

-- uniqueConstraints:用于指定唯一约束。

indexes : @Index(columnList="数据表中的列名", name="索引名")

indexes={@Index(), @Index()}

indexes={@Index(columnList="name", name="IDX_NAME"),

@Index(columnList="address", name="IDX_ADDRESS")} // 创建表中的索引

uniqueConstraints : @UniqueConstraint(columnNames={"列名","列名"}, name="唯一约束名")

uniqueConstraints={

@UniqueConstraint(columnNames={"name", "age"}, name="UC_NAME_AGE")}) // 多列建联合唯一约束

@Id() // 主键列

private Long id;

@Id() // 主键列

private String id;

主键自增长策略


主键生成策略:

@GeneratorValue(strategy=GenerationType.xxx)

-- GenerationType.IDENTITY: 适宜MySQL、SqlServer有自增长列的数据库。

-- GenerationType.SEQUENCE:适宜Oracle这种没有自增长有sequence的数据库。

-- GenerationType.AUTO:让Hibernate根据数据库方言自动选择主键生成策略。

-- GenerationType.TABLE: 适宜所有的数据库,因为它会单独生成一张表来维护主键生成

IDENTITY(自动增长生产策略)

@Id @GeneratedValue(strategy=GenerationType.IDENTITY)

private Integer id;

SEQUENCE(序列生成策略)

@Id @GeneratedValue(strategy=GenerationType.SEQUENCE)

private Integer id;

TABLE(生成一张表维护主键策略)

@Id @GeneratedValue(strategy=GenerationType.TABLE)

private Integer id;

AUTO(自动选择主键生成策略)

@Id @GeneratedValue(strategy=GenerationType.AUTO)

private Integer id;

@Column : 持久化类中属性转化成数据库表中列的相关信息

-- name:指定列名。

-- length: 该列支持的长度。

-- precision:有效的总位数。(BigDecimal)

-- scale:小数点的位数。(BigDecimal)

-- unique: 唯一约束。

-- nullable:非空约束。

-- insertable:是否允许插入true:允许 false: 不允许。

-- updatable:是否允许修改true:允许 false: 不允许。

-- columnDefinition :指定列的定义。

@Temporal(日期属性)

TemporalType.DATE(yyyy-MM-dd)

TemporalType.TIME(HH:mm:ss)

TemporalType.TIMESTAMP(yyyy-MM-dd HH:mm:ss) 默认

@Transient(指定不是持久化属性)

@Transient:指定不是持久化属性

transient:关键字修饰不需要序列化的属性,同时用它也能指定不是持久化的属性。

查询步骤


获取Session

获取Session:

Session session = sessionFactory.openSession();

定义hql查询语句

HQL 面向对象的查询 Student 是类名

select s from Student s

SQL 面向关系数据库的查询 t_student 是表名

select s.* from t_student as s

创建Query对象:

Query query = session.createQuery(hql);

调用query.setParameter("索引号", "值")设置hql语句中占位符的值。

获取查询结果

List<Object> lists = query.list();

Iterater<Object> iterater = query.iterate();

如果明确只有一条记录返回:

Object obj = query.uniqueResult();

分页查询

setFirstResult()方法设置limit 的第一个问号值

setMaxResults()方法设置limit 的第二个问号值.

hql语句


from子句:

语法:from|FROM 持久化类 [as? 对象名|别名]?

示例:

from Student

from Student as s

from Student s

查询表中所有的数据返回List<Student>.

sleect子句


select子句:

语法:

-- select 对象名|对象名.属性名 from 持久化类 as 对象名

-- select 属性名 from 持久化类

示范:

select s from Student s --> List<Student>

select s.name from Student s --> List<String>

select s.name, s.age from Student s --> List<Object[]>

select name, age from Student --> List<Object[]>

select s, s.name from Student s --> List<Object[]>


select new 子句: (可以改变List集合中存放的是什么)

语法:

-- select new 持久化类名(name, age) from Student : List<持久化类>

-- select new map(s.name as key, s.age as key) from Student s : List<Map> [{},{}] JSONArray

-- select new list(s.name, s.age) from Student s : List<List> [[],[]] JSONArray(二维数组)


where子句部分(查询过滤部分)

-- Hibernate的where子句部分能支持的运算符,表达式、函数特别多,用法与sql语句是一样的.

a.

b. 支持EJB-QL 3.0的函数:

trim(), lower(), upper(), length(), abs(), sqrt(), bit_length(), mod()


聚集函数(统计函数): count()、sum()、max()、min()、avg().


常用的表达式、运算符、函数:

=、<、<=、>、>=、!=、and、or、distinct、between...and 、like、concat()、

is null, is not null, is empty, is not empty、second(...),

minute(...), hour(...), day(...), month(...).


表达式


distinct(去掉重复)
concat(字符串连接)
between(在A和B之间)
not between(不在A和B之间)
使用like进行模糊查询
in(在指定的一个范围)
not in(不在指定的范围)
and并且条件连接
not like
or或者条件连接
not求反
is null(is empty)判断某个属性值是否为空
not is null(is not empty)判断某个值是否不为空

一级缓存(缓存的是对象):
-- 跟Session相关(存放在内存中).
-- 默认是开启的.
-- Session存活时间短,当Session关闭时,一级缓存将被清空,从而释放内存。


作用
提高CRUD操作的性能,当一级缓存中存在该对象时,
我们只要对该对象进行操作就可以影响表中这一行数据,
从而避免反复操作数据库表。

操作一级缓存的方法

     contains(Object object)
boolean contains(Object object)

-- 判断Session的一级缓存中是否包含一个对象,包含的话这个对象就是持久化状态。
    vict(Object object)
void evict(Object object)
-- 从Session的一级缓存中逐出一个对象.(该对象就不是持久化状态的对象).
flush()
void flush()
-- 将Session的一级缓存中的对象,同步到底层数据库表中.(立即同步)
clear()
void clear()
-- 清空Session的一级缓存,所有的持久化状态的对象都清空。(释放内存)
close()
void close()
-- 关闭Session,先调用flush(),再调用clear().
   
二级缓存

二级缓存(缓存的是对象):

-- 跟SessionFactory相关,因为SessionFactory存活的时间长。

-- 默认是关闭的.

-- 二级缓存中的对象存放到哪里,这个需要配置.

一般会配置内存中存放一些对象,超出了内存中放存的对象个数,就写入磁盘.

project/etc/ehcache.xml (配置二级缓存对象存放的配置文件).

注意:二级缓存只存储对象,不会存储单个属性:

例如: select s from Student s 会存储查询出来的s对象

select s.name from Student s 不会存储查询出来的单给属性

作用

二级缓存:

-- 提高查询效率

-- 当你做查询时,它会先到二级缓存中根据主键值找对象,

如果没找到就会到一级缓存中找对象,再没有找到就会到数据库表中查询该对象。

配置开启二级缓存

在hibernate.cfg.xml全局的配置文件中开启二级缓存:

<!-- 配置开启二级缓存 -->

<property name="hibernate.cache.use_second_level_cache">true</property>

<!-- 配置二级缓存的提供商 -->

<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>

拷贝二级缓存需要的jar包

lib\optional\ehcache

ehcache-2.10.1.jar

hibernate-ehcache-5.*.Final.jar

slf4j-api-1.7.7.jar

SLF4J : Simple Logging Facade for Java java的日志门面的jar包(日志规范).

ehcache.xml缓存配置文件

<ehcache>

<!-- diskStore: 配置二级缓存中的对象磁盘存储目录 -->

<diskStore path="F:\\ehcache"/>

<!-- 配置默认缓存区:

maxElementsInMemory : 配置二级缓存中的对象在内存中存放的最大数量.

eternal : 二级缓存中的对象是否永久有效。true: 永久有效、false: 不是永久有效.

timeToIdleSeconds : 配置二级缓存中的对象空闲的有效时间 120秒.

timeToLiveSeconds : 配置二级缓存中的对象存活的有效时间 120秒.

overflowToDisk : 配置二级缓存中的对象超出了内存中存放的最大数量,就写入磁盘.

-->

<defaultCache

maxElementsInMemory="10000"

eternal="false"

timeToIdleSeconds="120"

timeToLiveSeconds="120"

overflowToDisk="true"

/>

<!-- 配置命名的缓存区 -->

<cache name="yayadouCache"

maxElementsInMemory="10000"

eternal="false"

timeToIdleSeconds="120"

timeToLiveSeconds="120"

overflowToDisk="true"

/>

</ehcache>

配置哪些持久化类使用二级缓存

xml文件中配置

在hibernate.cfg.xml配置

<!-- 配置持久化类用二级缓存 -->

<class-cache usage="read-write" class="com.yayadou.domain.Teacher" region="yayadouCache"/>

持久化类上加注解

在持久化类上注解:

@Cache(usage=CacheConcurrencyStrategy.READ_WRITE, region="yayadouCache").

ehcache缓存并发策略


操作二级缓存


获取缓存对象(Cache)


Cache cache = sessionFactory.getCache()


containsEntity()
判断二级缓存中是否包含一个对象:
boolean containsEntity(Class entityClass, Serializable identifier);
boolean containsEntity(String entityName, Serializable identifier);



evictAllRegions()
清空二级缓存中所有的缓存对象:
void evictAllRegions();



evictEntity()
从二级缓存中踢出指定的对象:
void evictEntity(Class entityClass, Serializable identifier);
void evictEntity(String entityName, Serializable identifier);

evictEntityRegion()
从二级缓存中踢出指定类型的所有对象:
void evictEntityRegion(Class entityClass);
void evictEntityRegion(String entityName);

缓存统计信息


配置生成统计信息
hibernate.cfg.xml文件中配置生成统计信息:
<!-- 配置生成缓存的统计信息 -->
<property name="hibernate.generate_statistics">true</property>
<!-- 让Hibernate4用更友好的方式格式化统计信息 -->
<property name="hibernate.cache.use_structured_entries">true</property>
获取统计信息对象(Statistics)
Statistics statistics = sessionFactory.getStatistics();
获取二级缓存命中数量
获取二级缓存命中的数量: statistics.getSecondLevelCacheHitCount();
获取二级缓存错失数量
获取二级缓存错失的数量:statistics.getSecondLevelCacheMissCount();
获取二级缓存统计信息对象(SecondLevelCacheStatistics)
/** 获取学生的二级缓存的统计信息 */
SecondLevelCacheStatistics scs = statistics.getSecondLevelCacheStatistics("org.yayadou.domain.Student");
System.out.println(scs.getEntries());
对象在二级缓存中用什么格式保存。
Map集合:
-- key: 主键列的值.
-- value: 缓存对象,该对象对需要缓存的对象中的数据做了封装.


查询缓存

查询缓存(缓存的是查询语句):

-- 默认是关闭的.

-- 它是在二级缓存的基础之上.

查询缓存的缓存数据格式:

{"sql语句" : {"org.yayadou.hibernate.domain.Student" : [1,2,3,4,5,6],

"org.yayadou.hibernate.domain.Teacher" : [1,2]}}

注意:它要求hql语句要一致,而且hql语句中的占位符赋值也要一致,才能命中.

作用

提高查询效率.

-- 它缓存的是查询语句与查询出来的对象主键值.

在hibernate.cfg.xml文件中配置开启查询缓存.

<!-- 配置开启查询缓存 -->

<property name="hibernate.cache.use_query_cache">true</property>

调用query方法设置用查询缓存

在创建查询时需要设置用查询缓存:

query.setCacheable(true);


原创粉丝点击