回家呆了两个多星期,本该一星期学完的hibernate框架被拖了这么久。今天才把第二天的教程看完。做个简单的总结。
第一节 常用的主键生成策略
主键生成策略有几个,主要使用的是uuid和native
- uuid 通过hibernate自动生成一个32位的16进制字符串作为唯一标识符 实体类变量类型String
- native hibernate根据数据库类型自动选择 生成一个自增的标识符 实体类变量类型Integer
测试了一下increment策略,其同样是产生一个Integer类型自增主键,不过在生成时是先查询主键最大的数字然后根据这个数字在添加新的数据。sql语句如下
Hibernate: select max(hid) from t_home
Hibernate: insert into t_home (attr, tel, hid) values (?, ?, ?)
如果是native策略 则将主键在数据库中设置为自增。做添加操作时不会对主键进行设置,sql语句如下
Hibernate: insert into t_home (attr, tel) values (?, ?)
疑惑: 几种生成策略中没有发现与通过注释设置主键相同的方式。。。
第二节 CRUD操作
- 增加 session.save(user);
@Test
public void testSave() {
Session session = HbmUtil.getSession();
Transaction tx = session.beginTransaction();
User user = new User();
user.setUid(555); // 需要注意的是这里设置主键是无效的 hibernate会根据主键生成策略自动设置
user.setName("lee");
user.setPass("333");
session.save(user);
tx.commit();
session.close();
}
- 删除 session.delete(user);
@Test
public void testDelete() {
Session session = HbmUtil.getSession();
Transaction tx = session.beginTransaction();
// 第一种 获取持久化对象后删除
User user = session.get(User.class, 2);
session.delete(user);
// 第二种 通过托管态对象删除 不推荐
User user2 = new User();
user2.setUid(1);
session.delete(user2);
tx.commit();
session.close();
}
Hibernate: delete from t_user where uid=?
根据sql语句可知只要实体类中存在主键id且数据库中存在对应记录 就能进行删 若记录不存在则报错
- 修改 session.update(user);
@Test
public void testUpdate() {
Session session = HbmUtil.getSession();
Transaction tx = session.beginTransaction();
// 第一种 通过持久化对象自动修改
User user = session.get(User.class, 4);
user.setName("333333");
// 第二中 使用update修改
User user2 = session.get(User.class, 3);
user2.setPass("nihao");
session.update(user2);
// 第三中 通过托管态对象进行修改 必须所有字段都进行设置 不然就会用null代替 且主键必须存在不然报错 不推荐
User user3 = new User();
user3.setUid(11);
user3.setName("托管态");
user3.setPass("修改");
session.update(user3);
tx.commit();
session.close();
}
Hibernate: update t_user set uname=?, upass=? where uid=?
从sql语句看出每次都是全部更新 因此托管态的实体类必须对每个值都进行设置
什么是托管态,持久态下面有介绍
- 查询 session.get(User.class, id);
@Test
public void testQuery() {
Session session = HbmUtil.getSession();
Transaction tx = session.beginTransaction();
User user = session.get(User.class, 1);
System.out.println(user);
tx.commit();
session.close();
}
Hibernate: select uid, uname, upass from t_user where uid=?
第一个值传入实体类的class有没有和DBUtils里的ResultSetHandler接口很像,这只是个简单的查询,更复杂的在后面会有讲解
第三节 实体类的三种状态与saveOrUpdate
- 瞬时态 与session无关 不存在主键id
User user = new User();
user.setName("你好");
user.setPass("瞬时态");
- 持久态 与session相关 存在主键id
User user = session.get(User.class, 4);
// 持久态可实现自动更新 原因是内部存在快照 在事务提交前会进行对比 不一样则更新
user.setName("自动更新");
- 托管态 与session无关 存在主键id
User user = new User();
user.setUid(6);
user.setName("托管态");
user.setPass("嗨~");
- 三态的相互转换
* 瞬时态:执行session.save方法转化为持久态 添加id变托管态
* 持久态:session.delete转化瞬时 session.clear转化托管
* 托管态:删除id转发瞬时 session.update session.saveOrUpdate转化持久
- savaOrUpdate具体执行的操作
/**
* 测试SaveOrUpdate具体执行方式
* 实体类对象是瞬时态时做save操作
* 实体类对象是托管态时做update操作
* 实体类对象是持久态时做update操作
*/
@Test
public void testSaveOrUpdate() {
Session session = HbmUtil.getSession();
Transaction tx =session.beginTransaction();
// 瞬时态
User user = new User();
user.setName("你好");
user.setPass("瞬时态");
// session.saveOrUpdate(user);
// 托管态
// 托管态中的id在数据库中不存在则 报错
User user1 = new User();
user1.setUid(11);
user1.setName("又是托管态的修改");
user1.setPass("托管态");
session.saveOrUpdate(user1);
// 持久态
User user2 = session.get(User.class, 4);
user2.setName("持久态哈");
// session.saveOrUpdate(user2);
tx.commit();
session.close();
}
总结: 实体类带有id 且该id对应的记录在数据库中存在进行update操作 否则save操作
第四节 事务处理的标准写法
package cn.lkangle.twoday;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import cn.lkangle.entity.User;
import cn.lkangle.util.HbmUtil;
public class Standard {
@Test
public void test() {
Session session = null;
Transaction tx = null;
try {
session = HbmUtil.getSession();
tx = session.beginTransaction();
User user2 = new User();
user2.setName("回滚");
user2.setPass("测试");
session.save(user2);
// int s = 100/0;
User user = session.get(User.class, 2);
user.setName("测试回滚");
session.update(user);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
System.err.println("出现异常 回滚事务");
tx.rollback();
} finally {
System.out.println("关闭session");
session.close();
}
}
}
没有出现异常则正常提交事务,事务回滚写在catch中,出现异常则回滚事务,最后关闭session
第五节 绑定本地session
通过将session绑定在本地线程中达到一次事务中只存在一个session
- 配置hibernate.cfg.xml文件 添加下句
<!-- 绑定本地session 放在本地线程中 共三个值 一般用thread与本地线程绑定 -->
<property name="hibernate.current_session_context_class">thread</property>
- 通过 SessionFactory.getCurrentSession()获取
- 例子
LocalSession.java类
package cn.lkangle.twoday;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import cn.lkangle.util.HbmUtil;
public class LocalSession {
@Test
public void testLocal(){
Session session = HbmUtil.getCurrentSession();
Transaction tx = session.beginTransaction();
new addUser().saveUser();
tx.commit();
}
}
addUser.java类
package cn.lkangle.twoday;
import org.hibernate.Session;
import cn.lkangle.entity.User;
import cn.lkangle.util.HbmUtil;
public class addUser {
public void saveUser() {
User user = new User();
user.setName("新文件中添加");
user.setPass("测试事务中session处理");
Session session = HbmUtil.getCurrentSession();
session.save(user);
}
}
绑定本地的session不需要对session进行关闭,在线程结束后会自动关闭。
第六节 hibernate缓存
- 一级缓存: 默认开启 作用域在session
测试一级缓存存在
package cn.lkangle.twoday;
/**
* 一级缓存作用域session 从session创建到session关闭
* 证明存在一级缓存
* @author lbxx
*/
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import cn.lkangle.entity.User;
import cn.lkangle.util.HbmUtil;
public class Cache {
@Test
public void cacheTest() {
Session session = HbmUtil.getSession();
Transaction tx = session.beginTransaction();
User user = session.get(User.class, 1);
System.out.println(user);
/**
* 每次查询都会先在一级缓存中查找数据 如果发现则直接取出 如果没有发现则进行数据库查询
* 一级缓存默认打开 保存持久态的数据
*/
User user2 = session.get(User.class, 1);
System.out.println(user2);
tx.commit();
session.close();
}
}
两次查询只进行一次sql操作,第二次直接从缓存中获取
Hibernate:
select
user0_.uid as uid1_2_0_,
user0_.uname as uname2_2_0_,
user0_.upass as upass3_2_0_
from
t_user user0_
where
user0_.uid=?
name--> 新文件中添加 pass--> 测试事务中session处理
name--> 新文件中添加 pass--> 测试事务中session处理
- 二级缓存: 用户控制开启 作用域在SessionFactory
二级缓存暂未介绍
第七节 hibernate查询api 查询表中所有数据
调用两步走
- 创建对象
- 执行对象中方法
- Query对象
package cn.lkangle.twoday;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import cn.lkangle.entity.User;
import cn.lkangle.util.HbmUtil;
public class QueryTest {
@Test
public void testQuery() {
Session session = null;
Transaction tx = null;
try {
session = HbmUtil.getSession();
tx = session.beginTransaction();
Query<User> query = session.createQuery("from User");
List<User> list = query.list();
for (User user : list) {
System.out.println(user);
}
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
session.close();
}
}
}
- Criteria对象
package cn.lkangle.twoday;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import cn.lkangle.entity.User;
import cn.lkangle.util.HbmUtil;
public class CriteriaTest {
@Test
public void testCriteria() {
Session session = null;
Transaction tx = null;
try {
session = HbmUtil.getSession();
tx = session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
List<User> list = criteria.list();
for (User user : list) {
System.out.println(user);
}
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
session.close();
}
}
}
- SQLQuery对象
该对象默认查询返回值类型是数组 可以通过addEntity方法设置为对象类型
package cn.lkangle.twoday;
import java.util.Arrays;
import java.util.List;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import cn.lkangle.entity.User;
import cn.lkangle.util.HbmUtil;
public class SQLQueryTest {
@Test
public void sqlqueryTest() {
Session session = null;
Transaction tx = null;
try {
session = HbmUtil.getSession();
tx = session.beginTransaction();
SQLQuery sqlQuery = session.createSQLQuery("select * from t_user");
List<Object[]> list = sqlQuery.list();
for (Object[] objects : list) {
System.out.println(Arrays.toString(objects));
}
sqlQuery.addEntity(User.class);
List<User> list2 = sqlQuery.list();
for (User user : list2) {
System.out.println(user);
}
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
session.close();
}
}
}
更多的查询操作会在第四天进行讲解
有点疑惑的是这些方法好像都被弃用了
估计后面会有新的方式吧
end、、、