Day2

1 实体类编写规则

(1 ) 实体类中的属性是私有属性

(2) 私有属性要生成get与set方法

(3) 实体类中有属性作为唯一值(一般使用id值)

(4) 实体类属性建议不要使用基本数据类型, 应当使用基本数据类型的包装类

int ----> Integer

为什么建议我们使用包装类呢?

比如表示学生的分数, 如 int score;

-- 如果学生得了0分, int score=0;

-- 如果学生没有参加考试, 那么用int score=0; 不能准确表示学生是否参考试

-- 如果使用 Integer score;这样就要以解决缺考的问题 Integer score=null;

2 hibernate主键生成策略

(1 ) hibernate中要求实体类里面有一个属性作为唯一值, 对应表的主键, 主键可以有不同的生成策略

(2) hibernate中主键生成策略有很多种

(3) 在generator标签的class属性取值有多种,表示了不同的主键生成策略


-- native : 根据使用的数据库帮助我们选择哪个值

CREATE TABLE `t_person` (

`uid` int(1 1 ) NOT NULL AUTO_INCREMENT,

`uname` varchar(255) DEFAULT NULL,

`pword` varchar(255) DEFAULT NULL,

`addr` varchar(255) DEFAULT NULL,

PRIMARY KEY (`uid`)

)-

- uuid : 由hibernate帮助我们生成相应的UUID值

>使用uuid生成策略, 那么实体类的id类型必须是String

CREATE TABLE `t_person` (

`uid` varchar(255) NOT NULL,

`uname` varchar(255) DEFAULT NULL,

`pword` varchar(255) DEFAULT NULL,

`addr` varchar(255) DEFAULT NULL,

PRIMARY KEY (`uid`)

)

3 实体类操作n

(1 ) CRUD操作

-- 添加操作

-- 根据 id 查询返回一个对象

表中的现有的数据, 可以手动添加, 或通过session.save()方法添加

@Test

public void getPersonById(){

// 1 获取SessionFactory

SessionFactory sessionFactory=HibernateUtils.getSessionFactory();

// 2 获取session

Session session=sessionFactory.openSession();

// 3 开启事务

Transaction tx=session.beginTransaction();

// 4 根据id查询 调用session中的get方法

// Session.get(Class<Person> clazz, Serializable id)

// Class<Person> clazz : 类的class对象

// Serializable id : id值, 注意要求这个id类型是可序列化的

Person p1 =session.get(Person.class, 1 );

System.out.println(p1 );

// 5 提交事务

tx.commit();

// 6 关闭连接

session.close();

sessionFactory.close();

}-

- 更新对象

先根据id查询到对象, 再更新对象

@Test

public void updatePerson(){

// 1 获取SessionFactory

SessionFactory sessionFactory=HibernateUtils.getSessionFactory();

// 2 获取session

Session session=sessionFactory.openSession();

// 3 开启事务

Transaction tx=session.beginTransaction();

// 4.1 根据id查询 调用session中的get方法

Person p1 =session.get(Person.class, 2);

// 4.2 修改对象信息

p1 .setUname("张天明");

p1 .setPword("1 2345");

p1 .setAddr("中国南京");

// 4.3 调用 session的update()方法修改

// 修改过程, 到person表中, 根据id找到指定对象, 然后执行update语句完成修改

session.update(p1 );

// 5 提交事务

tx.commit();

// 6 关闭连接

session.close();

sessionFactory.close();

}

方法执行后显示的SQL语句

结果对比

-- 删除对象

@Test

public void deletePerson(){

// 1 获取SessionFactory

SessionFactory sessionFactory=HibernateUtils.getSessionFactory();

// 2 获取session

Session session=sessionFactory.openSession();

// 3 开启事务

Transaction tx=session.beginTransaction();

// 4 删除操作

// 第一种方式(常用的方式)

// 4.1 根据id查询 调用session中的get方法

Person p3=session.get(Person.class, 3);

// 4.2 对查询到的对象执行删除操作

session.delete(p3);

// 第二种方式(不常用)

// Person p2=new Person();

// p2.setUid(2);

// session.delete(2);

// 5 提交事务

tx.commit();

// 6 关闭连接

session.close();

sessionFactory.close();

}

结果查看

-- 添加或更新操作

@Test

public void saveOrUpdate_Person(){

// 1 获取SessionFactory

SessionFactory sessionFactory=HibernateUtils.getSessionFactory();

// 2 获取session

Session session=sessionFactory.openSession();

// 3 开启事务

Transaction tx=session.beginTransaction();

// 4 添加操作

Person person=new Person();

// 添加时是不用给uid的, 但是我现在给了,而且是且中已经存在的

person.setUid(1 );

person.setUname("东方不败");

person.setPword("5201 31 4");

person.setAddr("黑木崖");

// 执行添加

session.save(person);

// 5 提交事务

tx.commit();

// 6 关闭连接

session.close();

sessionFactory.close();

}

// 4 添加操作

Person person=new Person();

// 添加时是不用给uid的, 但是我现在给了,而且是且中已经存在的

person.setUid(1 );

person.setUname("东方不败");

person.setPword("5201 31 4");

person.setAddr("黑木崖");

// 执行添加

session.save(person);

上面的save操作并不是更新, 而是执行了保存操作, 且它能够自动处理id的问题

@Test

public void save_Update_Person(){

// 1 获取SessionFactory

SessionFactory sessionFactory=HibernateUtils.getSessionFactory();

// 2 获取session

Session session=sessionFactory.openSession();

// 3 开启事务

Transaction tx=session.beginTransaction();

// 4 添加操作

Person person=new Person();

// 添加时是不用给uid的, 但是我现在给了,而且是且中已经存在的

person.setUid(1 );

person.setUname("东方不败");

//person.setPword("5201 31 4");

person.setAddr("黑木崖");

// 执行修改操作

// 现在一般是先查再改, 我们也可以直接创建对象, 然后直接改, 但要给出准确的id

// 要注意了, 执行修改是对一个对象所有属性进行修改, 如果你有部分属性没有设置, 那么会置null

session.update(person);

// 5 提交事务

tx.commit();

// 6 关闭连接

session.close();

sessionFactory.close();

}

这是执行前后的结果比对

(2) 实体类对象状态(概念)

实体类状态有三种

--瞬时态:对象里面没有id值, 对象与session没有关联,一般是做添加操作

--持久态:对象有id值, 对象与seesion有关联

--托管态:对象有id值, 但对象与session没有关联

(3) saveOrUpdate方法;实现添加、 实现修改

--该方法很简单, 它会根据对象不同的状态做相应的操作

@Test

public void saveOrUpdate_Person(){

// 1 获取SessionFactory

SessionFactory sessionFactory=HibernateUtils.getSessionFactory();

// 2 获取session

Session session=sessionFactory.openSession();

// 3 开启事务

Transaction tx=session.beginTransaction();

// 4 添加操作

Person person=new Person();

// 添加时是不用给uid的, 但是我现在给了,而且是且中已经存在的

person.setUname("小龙女");

person.setPword("5201 31 4");

person.setAddr("古墓");

// 由于person是瞬时态, 那么saveOrUpdate()这时是做insert操作

session.saveOrUpdate(person);

Person p1 =session.get(Person.class, 1 );

p1 .setUname("杨过");

p1 .setPword("1 31 4520");

p1 .setAddr("古墓");

// 由于p1 是持久态, 那么saveOrUpdate()这时是做update操作

session.saveOrUpdate(p1 );

Person p2=new Person();

p2.setUid(2);

p2.setUname("乔峰");

p2.setPword("778899");

p2.setAddr("大辽");

// 由于p2是托管态, 那么saveOrUpdate()这时是做update操作

session.saveOrUpdate(p2);

// 5 提交事务

tx.commit();

// 6 关闭连接

session.close();

sessionFactory.close();

}

操作结果

4 hibernate的一级缓存

(1 ) 什么是缓存

-- 数据存到数据库里面, 数据库本身就是文件系统, 使用流的方式操作文件效率不高

-- 把数据存到内存里面, 不需要使用流方式, 可以直接读取内存中数据

-- 把数据放到内存中, 提高读取效率

(2) hibernate缓存

-- hibernate框架中提供很多优化方式, hibernate的缓存就是一个优化方式

-- hibernate缓存特点

第一类 hibernate一级缓存

> hibernate一级缓存默认打开

> hibernate一级缓存使用范围(有点类似于web阶段的requestScope,seeionScope)

一级缓存就是从session创建到session关闭的范围

> hibernate一级缓存中, 存储的数据必须是持久态的数据, 瞬时态与托管态的数据不会存储到一级缓存中

第二类 hibernate二级缓存

> 目前已经不使用了, 替代技术redis

> 二级缓存默认不是打开的, 需要通过配置打开

> 二级缓存使用范围, 是SessionFactory范围( 项目范围)

(3) 验证一级缓存存在

验证方式:

> 首先根据uid=1 查询, 返回对象 ( 查询数据库, 会有sql输出)

> 其次再根据uid=1 查询, 又会返回对象 (瞧一瞧会不会有sql 输出)

控制台输出

(4) 一级缓存执行过程

// 4 验证一级缓存

// 根据uid进行第一次查询,是否有sql语句输出

Person p1 =session.get(Person.class, 1 );

System.out.println(p1 );

// 再根据uid进行第二次查询,是否有sql语句输出

Person p2=session.get(Person.class, 1 );

System.out.println(p2);

步骤:

-- 首先查询一级缓存, 查询一级缓存如果没发现有相应的数据, 就去执行数据库查询

-- 查询数据库后, 会把查询得到的结果放到一级缓存中

-- 第二次进行查询时, 也会首先进行一级缓存查询, 这时发现数据已经在一级缓存中了, 直接取出就结果, 不会

再做数据库的查询

注意: 一级缓存中并不是存储某个对象, 而是把对象的属性值给存到缓存中, 当我们进行第二次查询时, 返回的

p2,其实是用之前存放的属性值给重新构建出来的一个新的对象噢, 这一点大家了解

(4) hibernate一级缓存特性

> 持久态会自动更新数据库

@Test

public void persistentUpdate(){

// 1 获取SessionFactory

SessionFactory sessionFactory=HibernateUtils.getSessionFactory();

// 2 获取session

Session session=sessionFactory.openSession();

// 3 开启事务

Transaction tx=session.beginTransaction();

// 4 持久态更新数据库

Person p5=session.get(Person.class, 5);

// 更新对象信息

p5.setUname("小师妹");

p5.setAddr("华山");

// 写入数据库,由于p5是持久态的, 所以下面的update方法调用可以省去

// session.update(p5);

// 5 提交事务

tx.commit();

// 6 关闭连接

session.close();

sessionFactory.close();

}

> 持久态会自动更新数据库的执行过程(了解)

5 hibernate的事务操作

(1 ) 什么是事务

数据库事务(Database Transaction) , 是指作为单个逻辑工作单元执行的一系列操作, 要么完全地执行, 要么完全地不执行。 事务

处理可以确保除非事务性单元内的所有操作都成功完成, 否则不会永久更新面向数据的资源。

http://baike.baidu.com/link?url=89WXbjUBGS86Qy9G2ynAxr97mBbnDHVmauvYQ_EGJ65CupbnF2TwUZiH9XvfhXuxEQUy9xBbJYWgnw_On8TJLRCbpXOuNQdHuLqJDlotPKjR_rPeBFHTmUmMAOVFDeEIKfSsUmimPHm2V5-F4r-dq

http://www.cnblogs.com/fjdingsd/p/5273008.html

hibernate设置事务隔离级别 http://www.cnblogs.com/jerryxing/archive/201 2/04/24/2468999.html

(2) 事务代码规则写法(重点掌握)

> 结构

try{

开启事务

处理代码

提交事务

}c

atch(){

回滚事务

}f

inally{

释放资源

}

@Test

public void addPerson_Standard() {

SessionFactory sessionFactory = null;

Session session = null;

Transaction tx = null;

try {

sessionFactory = HibernateUtils.getSessionFactory();

// 使用SessionFactory创建session对象

// 类似于jdbc连接, 只是这个地方hibernate做了封装

session = sessionFactory.openSession();

// 开启事务

tx = session.beginTransaction();

// 添加功能

Person person = new Person();

person.setUname("韦小宝");

person.setPword("weixiaobao");

person.setAddr("紫禁城");

// 调用session对象的实现方法,完成添加

session.save(person);

// 可以模拟一个异常

int a=1 0/0;

// 提交事务

tx.commit();

} catch (Exception e) {

// 输出异常

e.printStackTrace();

// 有异常, 则回滚事务

if(tx!=null){

tx.rollback();

}

} finally {

//关闭资源

if(session!=null && session.isOpen()){

session.close();

}if

(sessionFactory!=null && !sessionFactory.isClosed()){

sessionFactory.close();

}

}

}(2

) hibernate绑定session(重点掌握)

> session类似于jdbc的connection, 为了安全可以使用threadLocal

> hibernate已经帮助我们实现了与本地线程的绑定的session

> 获取与本地线程绑定的session

第一步 在hibernate核心配置文件中配置

<!-- 本地线程绑定的session -->

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

第二步 调用SessionFactory里面的方法得到

public class HibernateUtils {

private static SessionFactory sessionFactory = null;

private HibernateUtils() {

}s

tatic{

if (sessionFactory == null) {

Configuration cfg = new Configuration();

cfg.configure();

sessionFactory = cfg.buildSessionFactory();

}

}p

ublic static SessionFactory getSessionFactory() {

return sessionFactory;

}p

ublic static Session getLocalSessioin(){

// 直接返回与本地线程绑定的session

return sessionFactory.getCurrentSession();

}

}@

Test

public void addPerson_Standard2() {

Session session = null;

Transaction tx = null;

try {

// 通过工具类获取本地session

session = HibernateUtils.getLocalSessioin();

// 开启事务

tx = session.beginTransaction();

// 添加功能

Person person = new Person();

person.setUname("韦小宝");

person.setPword("weixiaobao");

person.setAddr("紫禁城");

// 调用session对象的实现方法,完成添加

session.save(person);

// 提交事务

tx.commit();

} catch (Exception e) {

// 输出异常

e.printStackTrace();

// 有异常, 则回滚事务

if(tx!=null){

tx.rollback();

}

} finally {

// 关闭资源(如果session是与本地线程绑定的, 那么它会自动关闭, 这个地方就用关闭了, 这么写也可以)

if(session!=null && session.isOpen()){

session.close();

}/

/ 注意在web项目中SessionFactory对象是不用关闭的, 因为它是大家共用的

}

}

6 hibernate的其他的api(查询)

(1 ) Query对象

> 使用Query对象, 不需要写sql语句, 我们要写hql语句

-- hql : hibernate query language, hibernate框架提供的查询语言, 这个hql和sql语句很相似

-- hql与sql的区别

>> 使用sql操作的是表和字段

>> 使用hql操作的是实体类和属性

-- 查询所有hql语句

>> from 实体类名称

-- Query对象的使用

>> 创建Query对象

>> 调用Query对象方法得到结果

@Test

public void personQuery() {

Session session = null;

Transaction tx = null;

try {

// 得到与本地线程绑定的session

session = HibernateUtils.getLocalSessioin();

// 开启事务

tx = session.beginTransaction();

// 查询person表的hql

String hql = "from Person";

// 创建Query对象

Query query = session.createQuery(hql);

// 通过Query对象得到查询结果

List<Person> persons = query.list();

// 遍历输出查询结果

for (Person p : persons) {

System.out.println(p);

}//

提交事务

tx.commit();

} catch (Exception e) {

// 有异常回滚

if(tx!=null){

tx.rollback();

}

} finally {

// 释放资源(当前的session是本地线程session, 可以不用下面语句)

if(session!=null && session.isOpen()){

session.close();

}

}

}

(2) Criteria对象

> 也可以使用这个对象进行查询操作, 但是使用这个对象时, 不需要写hql, 直接调用方法就可以实现

> 实现过程

-- 使用session对象的createCriteria(类名.class)创建Criteria对象

-- 调用criteria对象的list()方法返回结果集

(3) SQLQuery对象

> 使用hibernate时候, 我们也可以调用原始的sql语句, 它就是通过SQLQuery对象

>实现过程

-- 创建SQLQuery对象

-- 调用SQLQuery对象的方法得到结果

调试的结果

输出结果

怎么样能得到同上样直接返回一个List集合, 且集合中每一个都是Person类的对象呢?