Hibernate学习笔记②
1、实体类的编写规则
- JavaBean+属性中必须有唯一值的属性(对应数据库表的字段)
- 实体类属性不建议使用基本数据类型,建议使用基本数据类型对应的包装类
int - Integer char - Character 其他的都是首字母大写 比如 double - Double
为什么这样写呢?举例说 学生参加考试肯定有字段int score 如果他得了0分,sroce = 0就行了,但是如果这个学生没有参加考试,是没有score = null的,用Integer就可以使用 Interger score = null就可以了。
2、主键生成策略
<generator class="生成策略"></generator>
可选值:increment 每次增长 1
identity【只能用在mysql中】
sequenen【只能用在oracle中】
※ native 【根据使用的数据库 自动选择用的生成器 常用】
※ uuid 【生成32位唯一字符串】 Hibernate生成的不是任何一个(规范)版本的UUID,强烈不建议使用。
UUID是Universally Unique Identifier的缩写,它是在一定的范围内(从特定的名字空间到全球)唯一的机器生成的标识符。
3、CRUD操作
save 添加
get 根据id查询
/* * @param arg0 返回的实体类的Class * @param arg1 查询的id * */ User user = session.get(User.class, 2);
update 修改
① 先根据id查询 返回对象
② 在使用对象的setter方法修改值
③ session.update(对象)
修改也可以用session.save(对象)实现,但是最好用update方法。
delete 删除
【常用】第一种方式:
① 使用session.get查,返回对象
② session.delete(对象)
第二种方式:
① 实例化一个实体类,使用setter方法设置id为要删除的id
② 使用session.delete(对象)删除
4、实体类状态
瞬时态 没有id 和session也没有关系 瞬时态的实体类一般做save操作
持久态 有id值 与session有关联 session.get出的实体类就是持久态
托管态 有id值 与session没有关联 【不常用】 删除的第二种方法里面的实体类就是一个托管态实体类
另一个重要的方法 saveOrUpdate 根据实体类的状态执行不同的操作
实体类为瞬时态 -> saveOrUpdate做添加操作
实体类为持久态 -> saveOrUpdate做修改操作
实体类为托管态 -> saveOrUpdate做修改操作【不常用】
5、Hibernate一级缓存
缓存:放在内存中
有一级缓存和二级缓存
一级缓存特点:
- 一级缓存默认是打开的
- 使用范围是session范围【从创建session到关闭session的】
- 一级缓存的存储数据必须是持久态
注意:二级缓存已经不使用了,使用redis替代二级缓存
验证一级缓存的存在
User user = session.get(User.class, 2); System.out.println(user.getUsername()); User user1 = session.get(User.class, 2); System.out.println(user1.getUsername());
第一次查询时执行SQL,第二次查询时直接调用的缓存,并不执行SQL语句。
Hibernate: select user0_.uid as uid1_0_0_, user0_.username as username2_0_0_, user0_.password as password3_0_0_, user0_.address as address4_0_0_ from t_user user0_ where user0_.uid=? Dongfang Dongfang
Hibernate一级缓存的特性
- 持久态实体类改变数据时 自动修改【无需session.save或update】
- 原理:当一级缓存中没有持久态对象时会进行查询,查询后会放到一级缓存和以及对应的快照区【副本】中,当使用setter方法修改属性值时候,会同时修改一级缓存进行修改,但是不会修改一级缓存对应的快照区的值。当事务提交时,hibernate会比较一级缓存与快照区的内容是否相同,如果不相同会将一级缓存的内容更新到数据库中。
6、Hibernate事务操作
隔离性:避免事务并发问题的发生
不考虑隔离性会产生的问题:脏读、不可重复读、虚读
=》解决办法:设置事务隔离级别 repeatable read【mysql默认的事务隔离级别】
Hibernate中在hibernate.cfg.xml可以设置隔离级别,不常用
hibernate事务规范写法
事务要有提交也要有回滚。
代码结构:
try{
//开启事务 Transaction tx = session.beginTransaction()
//提交事务 tx.commit()
}
catch{
//回滚事务 tx.rollback()
}
finally{
//关闭事务/*无论有没有异常 都会被关闭*/
tx.close();
}
7、hibernate与Session绑定
作用:确保session是唯一的,不共享的
方法:将session与本地线程绑定
<!-- 配置session绑定本地线程 --> <property name="current_session_context_class">thread</property>
然后在HibernateUtil中增加getCurrentSession方法
public static Session getCurrentSession() { return sessionFactory.getCurrentSession(); }
此时返回的Session对象就是与线程绑定的Session对象。
此时不需要手动关闭session,因为与本地session绑定了。
8、Hibernate API - 查询
- Query
- Criteria
- SQLQuery
(1)Query对象
- 写HQL语句,不写SQL
- HQL操作的是实体类
e.g. 查询所有的HQL: from 实体类的名称
//创建Query对象 Query query = session.createQuery("from User"); List<User> userlist = query.list(); for(User user : userlist) { System.out.println(user.getUsername()); }
(2)Criteria对象
不需要写语句,直接调用方法即可。
Criteria c = session.createCriteria(User.class); List<User> userlist = c.list(); for(User user : userlist) { System.out.println(user.getUsername()); }
session.createCriteria(User.class); 提示是过时的方法
(3)SQLQuery对象
SQLQuery sqlquery = session.createSQLQuery("select * from t_user");
List<Object[]> list = sqlquery.list(); //默认返回的是数组的形式
让返回的list的每部分为实体类对象
SQLQuery sqlquery = session.createSQLQuery("select * from t_user"); sqlquery.addEntity(User.class); List<User> list = sqlquery.list();
通过设置addEntity来达到返回的是实体类的对象
上面的方法提示全部过时