hibernate学习(2)
1 实体类编写规则
2 hibernate主键生成策略
3实体类操作
(1)crud操作
(2)实体对象状态
4 hibernate的一级缓存
5 hibernate事务操作
(1)事务代码规则写法
6 hibernate其他的api(查询)
实体类编写规则
1 实体类里面属性私有的
2 私有属性使用公开的set方法和get方法操作
3 要求实体类有属性作为唯一值(一般都使用id值)
4 实体类属性建议不使用基本数据类型,使用基本数据类型对应的包装类。
(1)八个基本数据类型对应的包装类
-int - Integer
-char--Character
-其他的都是首字母大写 比如double-Double
(2)比如表示学生的分数,假如 int score;
-比如学生得了0分,int score-0;
-如果表示学生没有参加考试,int scrore无法为null,int score不能准确表示学生是否参加考试
解决:使用包装类可以了,Integer score=0,学生得了0分
表示学生没有参加考试,Integer score=null;
Hibernate主键生成策略
1 hibernate要求实体类里面有一个属性作为唯一值,对应主键,主键可以不同生成策略
2 hibernate主键生成策略有很多的值
<!-- 设置数据库id增长策略 native:生成表id值就是主键自动增长 -->
<generator class="native"></generator>
主要记住native和uuid。
identity只能用在mysql中,sequence只能用在oracle中。
因为不知道用什么数据库,所以用native,它会帮我们根据不同的数据库选择不一样的值。
(1)native:根据使用的数据库帮我们选择哪个值
CREATE TABLE `t_user` (
`uid` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) DEFAULT NULL,
`password` varchar(255) DEFAULT NULL,
`address` varchar(255) DEFAULT NULL,
PRIMARY KEY (`uid`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 |
(2)uuid:hibernate帮我们生成uuid值。
(1)使用uuid生成策略,实体类id属性类型必须是字符串类型。
在User.java中
private String uid;
//如果有哪个属性值没有生成get和set方法,那么程序会出现异常
在User.hbm.xml中
<generator class="uuid">
</generator>
show create table t_user;展示如下所示:
CREATE TABLE `t_user` (
`uid` varchar(255) NOT NULL,
`username` varchar(255) DEFAULT NULL,
`password` varchar(255) DEFAULT NULL,
`address` varchar(255) DEFAULT NULL,
PRIMARY KEY (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
实体类操作
对实体类crud操作
添加操作
1 调用session里面的save方法实现
//添加功能
User user = new User();
user.setUsername("xiaoMA");
user.setPassword("250");
user.setAddress("China");
session.save(user);
根据id查询
hibernate可以帮我们创建表,但无法创建数据库。
1 调用session里面的get方法实现
//4 根据id查询
//调用session里面的get方法
//第一个参数:实体类的class
//第二个参数:id值
User user = session.get(User.class, 1);
底层输出语句
<!-- 输出底层sql语句 -->
<property name="hibernate.show_sql">true</property>
的输出结果是:
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=?
User [uid=1, username=lucy, password=123, address=china]
修改操作
(1)根据id查询,返回对象
// 4 修改操作
// 修改uid=2记录username值
User user = session.get(User.class, 2);
//4.2向返回的user对象里面设置修改之后的值
user.setUsername("dongfangbubai");
//4.3 调用session方法update修改
//执行过程:到user对象里面找到uid值,根据uid进行修改
session.update(user);
底层代码
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=?
Hibernate:
update
t_user
set
username=?,
password=?,
address=?
where
uid=?
删除操作
// 4 删除操作
// 第一种 根据id查询对象
User user = session.get(User.class, 2);
session.delete(user);
第二种删除方式
//第二种
User user = new User();
user.setUid(3);
session.delete(user);
save和update
在表中已经有了uid值为1的数据,再执行下面语句,有的(主键不是自动增长的)运行会报错,有的会另外增加一条数据(uid值不一样)。
User user = new User();
user.setUid(1);
user.setUsername("mary");
user.setPassword("250");
user.setAddress("yuenan"); session.save(user);
同样下面代码,运行不会报错,
User user = new User();
user.setUid(1);
user.setUsername("tom"); session.update(user);
但是导致剩余没有赋值的字段为空
所以一般都不建议这样做。
实体类对象状态(概念)
1 实体类状态有三种
(1)瞬时态:对象里面没有id值,对象与session没有关联
User u = new User();
u.setUsername("jack");
u.setPassword("124");
u.setAddress("China");
session.save(u);
(2)持久态:对象有id值,对象与session有关联
User user = session.get(User.class, 1);
(3)托管态:对象有id值,对象与session没有关联
User user = new User();
user.setUid(3);
2 演示操作实体类对象的方法
(1)saveOrUpdate方法:实现添加、实现修改
瞬时态对象
//1 添加操作
User user = new User();
user.setUsername("jack");
user.setPassword("520");
user.setAddress("north korean"); //实体类对象状态是瞬时态,做添加操作
session.saveOrUpdate(user);
托管态对象
User user = new User();
user.setUid(2);//表中有uid为2的数据
user.setUsername("rose");
user.setPassword("1234");
user.setAddress("aerbaliya"); //实体类对象状态是托管态,做修改操作
session.saveOrUpdate(user);
查询先后结果如下所示:
持久态对象
//持久态
User user = session.get(User.class,7);
user.setUsername("rose"); //实体类对象状态是持久态,做修改操作
session.saveOrUpdate(user);
运行报错,不知是不是主键没有设置动态增长的原因。
Hibernate的一级缓存
什么是缓存
1 数据存到数据库里面,数据库本身是文件系统,使用流方式操作文件,效率并不是很高。
(1)把数据存到内存中,不需要使用流的方式,可以直接读取内存中数据
(2)把数据放到内存中,提供读取效率
Hibernate缓存
1 hibernate框架中提供了很多优化方式,hibernate的缓存就是一种优化方式
2 hibernate缓存特点:
第一类 hiberante的一级缓存
(1)hibernate的一级缓存默认打开的
(2)hibernate的一级缓存使用范围,是session的范围,从session创建到session关闭范围
(3)hibernate的一级缓存中,存储数据必须是持久态数据
第二类 hibernate的二级缓存
(1)目前已经不使用了,替代技术redis
(2)二级缓存默认不是打开的,需要配置
(3)二级缓存使用范围,是sessionFactory范围
验证一级缓存存在
1 验证方式
(1)首先根据uid=1查询,返回对象
(2)其次再根据uid=1查询,返回对象
//1 根据uid=2查询
// 执行第一个get方法是否查询数据库,是否发送sql语句
User user1 = session.get(User.class, 2);
System.out.println(user1); //2 再根据uid=6查询
//执行第二个get方法是否查询数据库,是否发送sql语句
User user2 = session.get(User.class, 2);
System.out.println(user2);
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=?
User [uid=2, username=rose, password=5678, address=aerbaliya]
User [uid=2, username=rose, password=5678, address=aerbaliya]
第一步执行get方法之后,发送sql语句查询数据库
第二个执行get方法之后,没有发送sql语句,查询一级缓存内容。
一级缓存的执行过程
Hibernate一级缓存特性
1 持久态自动更新数据库
//1 根据id查询
User user = session.get(User.class, 1);
//2 设置返回对象
user.setUsername("hanmeimei");
//3 调用方法实现
session.update(user);
2 执行过程(了解)
Hibernate事务操作
事务相关概念
1 什么是事务
2 事务的特性
3 不考虑隔离性产生问题
(1)脏读
(2)不可重复读
(3)虚读
4 设置事务隔离级别
(1)MySQL默认隔离级别 repeatable read
Hibernate事务代码规范写法
1 代码结构
try{
开启事务
提交事务
}catch(){
回滚事务
}finally{
关闭
}
// 事务规范代码
@Test
public void testTx() {
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null;
try {
sessionFactory = HibernateUtils.getSessionFactory();
session = sessionFactory.openSession();
// 开启事务
tx = session.beginTransaction();
// 添加
User user = new User();
user.setUsername("xiaoma");
;
user.setPassword("250");
user.setAddress("american"); session.save(user); int i = 10 / 0; // 提交事务
tx.commit();
} catch (Exception e) {
// 回滚事务
e.printStackTrace();
tx.rollback();
} finally {
session.close();
sessionFactory.close();
} }
Hibernate绑定session
1 session类似于jdbc的connection,之前web阶段学过threadLocal
2 帮我们实现与本地线程绑定session
3 获取与本地线程绑定的session
(1)在hibernate核心配置文件中配置
使用单线程
<!-- 在hibernate核心配置文件中配置 -->
<property name="hibernate.current_session_context_class"></property>
(2)调用sessionFactory里面的方法得到
//提供返回与本地线程绑定的session的方法
public static Session getSessionObject(){
return sessionFactory.getCurrentSession();
}
4 获取与本地线程绑定session时候,关闭session报错,不需要手动关闭。它会自己关闭。
不需要session.close()方法了,如果是用sessionFactory.openSession()得到的session,才需要sesssion.close();报错如下所示:
org.hibernate.SessionException: Session was already closed
at org.hibernate.internal.SessionImpl.close(SessionImpl.java:411)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:338)
at com.sun.proxy.$Proxy25.close(Unknown Source)
at cn.itcast.hibernatetest.HibernateSelect.testTx01(HibernateSelect.java:38)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
解决办法:去掉session.close()语句即可。
Hibernate的api使用
Query对象
1 使用query对象,不需要写sql语句,但是写hql语句
(1)hql:hibernate query language,hibernate提供查询语言,这个hql语句和普通sql语句很相似
(2)hql和sql语句区别:
-使用sql操作表和字段
-使用hql操作实体类和属性
2 查询所有hql语句:
(1) from实体类名字
3 Query对象使用
(1)创建Query对象
(2)调用query对象里面的方法得到结果
// 1 创建Query对象
Query query = session.createQuery("from User");
//这里加上的是实体类的名字 // 2 调用query对象里面的方法得到结果
List<User> list = query.list(); for (User user : list) {
System.out.println(user);
}
Criteria对象
1 使用这个对象查询操作,但是使用这个对象的时候,不需要写语句,直接调用方法实现
2 实现过程
(1)创建criteria对象
(2)调用对象里面的方法得到结果
//1 创建criteria对象
//方法里面的参数是实体类class
Criteria criteria = session.createCriteria(User.class);
//2 调用方法得到结果
List<User> list = criteria.list();
for(User user : list){
System.out.println(user);
}
SQLQuery对象
1 使用hibernate的时候,调用底层sql实现
2 实现过程
(1)创建对象
(2)调用对象的方法得到结果
返回list集合每部分是数组
//1 创建对象
// 参数普通sql语句
SQLQuery sqlQuery = session.createSQLQuery("select * from t_user");
//调用sqlQuery里面的方法
//返回list集合,默认里面每部分是数组结构
List<Object[]> list = sqlQuery.list(); for(Object[] objects : list){
System.out.println(Arrays.toString(objects));
}
现在要求list返回的是对象
要对sqlQuery进行设置,使用它的addEntity(User.class)设置吧数据放到那个实体类中去。
//1 创建对象
// 参数普通sql语句
SQLQuery sqlQuery = session.createSQLQuery("select * from t_user"); //返回的list中每部分是对象形式
sqlQuery.addEntity(User.class); //调用sqlQuery里面的方法
List<User> list = sqlQuery.list(); for(User user : list){
System.out.println(user);
}
hibernate学习(2)的更多相关文章
- Hibernate学习之——搭建log4j日志环境
昨天讲了Hibernate开发环境的搭建以及实现一个Hibernate的基础示例,但是你会发现运行输出只有sql语句,很多输出信息都看不见.这是因为用到的是slf4j-nop-1.6.1.jar的实现 ...
- Hibernate学习笔记(二)
2016/4/22 23:19:44 Hibernate学习笔记(二) 1.1 Hibernate的持久化类状态 1.1.1 Hibernate的持久化类状态 持久化:就是一个实体类与数据库表建立了映 ...
- Hibernate学习笔记(一)
2016/4/18 19:58:58 Hibernate学习笔记(一) 1.Hibernate框架的概述: 就是一个持久层的ORM框架. ORM:对象关系映射.将Java中实体对象与关系型数据库中表建 ...
- Hibernate 学习笔记一
Hibernate 学习笔记一 今天学习了hibernate的一点入门知识,主要是配置domain对象和表的关系映射,hibernate的一些常用的配置,以及对应的一个向数据库插入数据的小例子.期间碰 ...
- Hibernate学习笔记-Hibernate HQL查询
Session是持久层操作的基础,相当于JDBC中的Connection,通过Session会话来保存.更新.查找数据.session是Hibernate运作的中心,对象的生命周期.事务的管理.数据库 ...
- 我的hibernate学习记录(二)
通过上一篇文章我的hibernate学习记录(一)基本上的入门了hibernate,但是,里面还有还多东西是通过迷迷糊糊的记忆,或者说copy直接弄进去的,所以这篇文章就需要对上篇的一些文件.对象进行 ...
- Hibernate学习(二)关系映射----基于外键的单向一对一
事实上,单向1-1与N-1的实质是相同的,1-1是N-1的特例,单向1-1与N-1的映射配置也非常相似.只需要将原来的many-to-one元素增加unique="true"属性, ...
- Hibernate学习一:Hibernate注解CascadeType
http://zy19982004.iteye.com/blog/1721846 ———————————————————————————————————————————————————————— Hi ...
- Hibernate学习---缓存机制
前言:这些天学习效率比较慢,可能是手头的事情比较多,所以学习进度比较慢. 在之前的Hibernate学习中,我们无论是CURD,对单表查询还是检索优化,我们好像都离不开session,session我 ...
- hibernate学习系列-----(2)hibernate核心接口和工作机制
在上一篇文章hibernate学习系列-----(1)开发环境搭建中,大致总结了hibernate的开发环境的搭建步骤,今天,我们继续了解有关hibernate的知识,先说说这篇文章的主要内容吧: C ...
随机推荐
- vnc server配置、启动、重启与连接
目前有两种比较流行的方式:XDM(X display manager)方案和VNC方案,而我个人比较倾向于VNC方案,一是因为VNC方案配置起来相对比较容易,二是VNC方案支持多种连接方式,比如通过浏 ...
- 解决You are using pip version 9.0.1, however version 9.0.3 is available. You should consider upgra
直接运行命令:python -m pip install --upgrade pip
- PsySH——PHP交互式控制台
PsySH PsySH is a runtime developer console, interactive debugger and REPL for PHP. PsySH是一个PHP的运行时开发 ...
- 使用BUCK进行iOS项目打包
关于BUCK BUCK是Facebook开源的快速打包工具,可以用于多种语言及平台的项目打包,例如:C.C++.Java.iOS.Android等等.用于大型的iOS.Android项目,可以显著提升 ...
- Ajax在jQuery中的应用---ajax()方法
在jQuery中,$.ajax()方法是最底层的方法,也是功能最强的方法.其调用的语法格式为: $.ajax([options]) 其中,可选项参数[options]为$.ajax()方法中的请求设置 ...
- sudoers文件设置sudo命令无密码(root密码)登录
参考博客:http://xvshell.iteye.com/blog/1838093 1. 当用户执行sudo时,Linux系统会去寻找/etc/sudoers文件,并且这是主动的,判断用户是否有执行 ...
- vuex的 例子
最近在学习vuejs,一直有听说vuex,用来实现多组件共享的一种状态管理模式,但是网上都说,不要为了用vuex而用vuex,大概意思就是尽量少用vuex,一些小项目可以用bus来实现组件之间的传值问 ...
- cocos2d关于glew32.lib错误(转)
应项目需要使用cocos2d-x开发,又要学习新东东了.·cocos2d-x 是一个支持多平台的 2D 手机游戏引擎,用C++重写cocos2d-iphone引擎的一个开源项目,想了解更多的童鞋美去百 ...
- BEM(一种 CSS 命名规则)
一. 什么是 BEM BEM的意思就是块(block).元素(element).修饰符(modifier),是由 Yandex 团队提出的一种前端命名方法论. 这种巧妙的命名方法让你的 CSS 类对其 ...
- JQuery3 的新变化
1. for-of 循环 for-in 循环不被推荐遍历数组,forEach 循环不能中断,for-of 循环(ES6)则弥补了前两者的不足,又添加了更多拓展(比如能遍历字符串,DOM 元素等) 因此 ...