hibernate复习第(4)天
1、hibernate的映射类型。
hbm.xml中property中的type属性。
这个type属性是表示持久化类中的属性对应数据库中的什么数据类型,用来构建一种映射
type的可选值:
hibernate的内建类型:
integer,long,short,float....
string
date,time,timestamp
....
java的类型:必须加上全包名,比如:java.lang.Integer
type一般都有自己的缺省值,大多数情况下不需要设置。
设置type的场合:
比如我设置持久化类类型为Date类型,我希望保存到数据库中只是有日期没有时间,缺省状态下type是timestamp,保存的是日期和时间都有,这时候我们需要将type属性设置成为time即可。
2、
Session的内部缓存管理
flush():将一级缓存与数据库进行同步
这是什么意思呢?就是hibernate在处理与数据库有关的操作的时候,只有必要的时候才会立刻与数据库进行交互,一般是将处理数据库的语句堆叠在一起,然后在commit()的时候再一起进行与数据库的交互,这样可以提高性能。当然如果在commit()之前查询了前面save的数据,它是会先与数据库交互的,所以说是在不必要的情况下将与数据库的交互堆叠在commit为信号处理。
flush方法就是将一级缓存与数据库同步,之前未交互的数据是在缓存中的,使用flush方法就直接执行缓存中的所有的sql交互语句,不需要到commit了。
例子:
大批处理:
大量操作数据可能会造成内存溢出,解决方法如下:
1、定时清除session中的数据
for(int i=0;i<100000;i++){
session.save(obj);
if(i%50==0){
session.flush();//这一步需要进行,否则怕丢失数据
session.clear();
}
}
2、使用StatelessSession接口,该接口不会与一二级缓存交互,也不会触发任何事件、监听、拦截,通过该接口的操作会立刻发送给数据库,和JDBC功能一样。
StatelessSession ss=HibernateUtil.getSessionFactory().openStatelessSession();
该接口的使用与普通session类似
3、Query.executeUpdate()执行批量更新,会清除相关联的一二级缓存(sessionFactory.evict(class)),可能造成级联和乐观锁定出现问题
Query query=s.createQuery("update u set Date=:dt from User");
query.setDate("dt", new Date());
query.executeUpdate();
HQL:
查询多个对象,返回的是对象数组。
select art,user from Article art,User user where art.author.id=user.id and art.id=:id 返回的是Object[] Object[0]:article,Object[1]:user
我们一般查询的都是整个对象而不是该对象的某几个属性,因为如果查询的是某几个属性不方便转换,建议查询整个对象,然后从对象中取值。
在已知id的情况下建议使用get()或者load()查询而不是hql语句或者criteria查询,因为前者会使用缓存而后者不会。所有有一个性能的问题选择
分页:query.setFirstResult,query.setMaxResults
查询记录总数:query.iterator("select count(*) from Person").next()
批量更新query.executeUpdate()可能造成二级缓存数据失效
Criteria:
排序:Criteria.addOrder(Order.desc(propertyName));
关联查询:criteria.setFetchMode("propertyName",FetchMode.SELECT) 和映射文件属性中设置fetch一样
投影:Projections.rowCount(),max(PropertyName),avg,groupProperty...
分页:Projections.RowCount(),criteria.setFirstResult(),criteria.setMaxResults()
离线查询:DetchedCriteria可在session外创建,然后使用getExecuteableCriteria(Session)创建Criteria对象来完成查询
Example查询,Example.create(obj),criteria.add(example)
N+1查询:
iterator方法:
iterator方法的步骤:首先查询出所有结果集的对应的id的列表,然后根据id查询各个数据列。所以叫做n+1次。iterator中的n次的时候可以使用缓存。
其他N+1地方:
懒加载获取关联对象:
遍历查询一对多中多的信息。应为一对多中使用懒加载,只有使用它属性才会查询,所以查询所有有n次,前面查询父对象需要一次
如果打开对查询的缓存,即list也可能有n+1次缓存
hibernate中的监听(event)
hibernate中也可以使用监听,执行save等前后的操作。
第一步:
书写监听器,实现特定接口。书写代码:
public class SaveListener implements SaveOrUpdateEventListener{ public void onSaveOrUpdate(SaveOrUpdateEvent event)
throws HibernateException {
Object obj=event.getObject();
if(obj.getClass().getSimpleName().equals("User")){
User u=(User) obj;
System.out.println(u.getName().getFirstName());
}
} }
第二步:配置监听器
<event type="save">
<listener class="cn.itcast.web.listener.SaveListener"/>
</event>
其他的就是使用了!
注意:hibernate中默认的save等方法进行sql操作是通过监听完成的,如果你单纯的配置自己的监听,那么hibernate会以为你拥有更好的实现sql操作的方式,所有会发现你无法插入数据到数据库中。这个时候,你可以再配置一个监听器,也就是默认的监听器。监听器的执行步骤和配置顺序一致
<event type="save">
<listener class="cn.itcast.web.listener.SaveListener"/>
<listener class="org.hibernate.event.def.DefaultSaveOrUpdateEventListener"/>
</event>
SQL和命名查询
在hibernate中使用SQL语句进行查询,使用SQLQuery接口
static User query(int id){
Session s=null;
try{
s=HibernateUtil.getSession();
User user=(User) s.load(User.class, id);
//user.getName(); 在session关闭前简单使用下该对象,就会立刻加载过来了。不建议这样使用,因为调用该对象的语句看起来没有意义可能被误删
Hibernate.initialize(user); //建议使用这种方式
return user;
}finally{
if(s!=null) s.close();
}
}
命名查询:
在映射文件中配置命名参数,然后在dao中直接使用命名参数生成query对象。
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping
package="cn.itcast.domain"> <class name="User" table="user">
<!--
<cache usage="read-write"/>
--> <id name="id">
<generator class="increment"/>
</id> <version name="ver" type="timestamp"/> <!-- 缺省状态是int类型 --> <!-- <timestamp name="ver"/>--><!-- 类型只能是Date类型 -->
<property name="birth"/>
<component name="name" class="Name">
<property name="firstName" column="first_name"/>
<property name="lastName" column="last_name"/>
</component> <query name="findUserById1">
<![CDATA[from User where id=:id]]>
</query> </class> <query name="findUserById">
<![CDATA[from User where id=:id]]>
</query> <sql-query name="findUser">
<![CDATA[select * from user]]>
</sql-query> </hibernate-mapping>
命名查询的配置地点是在hbm映射文件中,可以在class之内配置也可以在class之外配置。
配置在class之外,相当于整个项目的成员变量,使用的时候:
Query query=s.getNamedQuery("findUser");直接使用nameshuxi9ng即可,但是,注意name是唯一的,不允许重复
如果配置在class之内,使用的时候使用全路径。
使用:
s=HibernateUtil.getSession();
Query query=s.getNamedQuery("findUserById");
query.setInteger("id", );
User user=(User) query.list().get();
System.out.println(user.getName()+"--"+user.getBirth()); Query query=s.getNamedQuery("cn.itcast.domain.User.findUserById1");
命名查询不只是可以配置hql查询,也可以配置sql查询:
<sql-query name="findUser">
<![CDATA[select * from user]]>
</sql-query> Query query=s.getNamedQuery("findUser");
List<Object[]> user=query.list();
Object[] u=user.get();
System.out.println(u[]+"---"+u[]+"---"+u[]);
hibernate的最佳实践:
1、多使用细粒度的组件,componment
2、主键最好无意义
3、最好每一个持久类对应一个映射文件
4、考虑把查询字符串放到程序外面,也就是使用命名查询
5、使用绑定变量:=name
6、不要把异常看成可恢复的,尽量使用RuntimeException而不是Exception
7、考虑将hibernate代码从业务逻辑代码中抽象出来
8、多使用双向关联
hibernate复习第(4)天的更多相关文章
- Hibernate复习之Hibernate基本介绍
众所周知.眼下流行的面向对象的对象关系映射的Java持久层框架有MyBatis和Hibernate.他们都是对象关系映射ORM. 解决的主要问题就是对象-关系的映射.域模型和关系模型都分别建立在概念模 ...
- Hibernate复习
第一天 Hibernate是一个持久层的ORM框架.两个配置文件, 类名.hbm.xml类的属性和表的列对应 hibernate.cfg.xml核心配置文件 Hibernate相关API: Confi ...
- hibernate复习第(三)天
今日要点: 1.继承关系映射 一个表对应一个映射树(subclass) 一个子类一个表,子类只有父类没有的字段(joined-subclass) 鉴别器和内连接结合使用(subclass join) ...
- hibernate复习第(二)天
今日要点: 关联映射 多对一(Employee - Department) 一对多(Department - Employee) 一对一(Person - IdCard) 多对多(teachet - ...
- hibernate复习第(一)天
首先导入jar. 这个版本是3.2.5 开发流程: 1.由Domain object ->mapping ->db (官方推荐) 2.由DB开始,使用工具生成mapping和Domain ...
- HIBERNATE知识复习记录4-HQL和QBC
Hibernate中共提供了三种检索方式:HQL(Hibernate Query Language).QBC.QBE(Query By Example). HQL 是Hibernate Query L ...
- HIBERNATE知识复习记录3-关联关系
先上一张图,关于几种关系映射: 抄一段解释: 基本映射是对一个实体进行映射,关联映射就是处理多个实体之间的关系,将关联关系映射到数据库中,所谓的关联关系在对象模型中有一个或多个引用.关联关系分为上述七 ...
- HIBERNATE知识复习记录1-连接及常用方法
要去面试了,复习一下HIBERNATE的相关知识吧,原来边看视频边写的代码如下,已经分不清先后次序了,大致看一看吧. 先看下总的配置文件hibernate.cfg.xml: <?xml vers ...
- Hibernate 知识点复习
核心接口 1 Configuration接口负责配置并启动Hibernate,创建SessionFactory对象 2 SessionFactory接口负责初始化Hibernate.它充当数据存储 ...
随机推荐
- Java反射获取对象成员属性,getFields()与getDeclaredFields()方法的区别
Java反射获取对象成员属性,getFields()与getDeclaredFields()方法的区别 在工作中遇到一个问题,就是你需要去判断某个字符串是不是对象的某个成员属性名,然后根据判断结果 ...
- python3读取BJDA药品经营企业数据
#-*- coding:utf-8 -*- #读取北京FDA的药品经营企业数据 # 20161125 zhangshaohua import re import urllib.request impo ...
- selenium 遇到chrome 弹出是否保存密码框
--待验证(以下是java脚本) ChromeOptions options = new ChromeOptions(); options.addArguments("--start-max ...
- ps -ef 和 aux 区别
Linux中的ps命令是Process Status的缩写.ps命令用来列出系统中当前运行的那些进程.ps命令列出的是当前那些进程的快照,就是执行ps命令的那个时刻的那些进程,如果想要动态的显示进程信 ...
- local variable 'xxx' referenced before assignment(犯过同样的错)
这个问题很囧,在外面定义了一个变量 xxx ,然后在Python的一个函数里面引用这个变量,并改变它的值,结果报错local variable 'xxx' referenced before assi ...
- SWD下载调试填坑,SWD连接丢失问题解决
野火SWD下载器,设置好以后,第一次下载成功,莫名其妙丢失连接,发现在复位状态可以连接(惊奇) 网络上搜索到把Boot0和Boot1置高,就可以把程序下载到RAM里, 能下载以后就好办了,把程序里SW ...
- swagger api 文档框架
<其他教程:https://www.cnblogs.com/FlyAway2013/p/7510279.html> 先看看swagger的生态使用图: 其中,红颜色的是swaggger官网 ...
- 九度OJ 1349:数字在排序数组中出现的次数 (排序、查找)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:2489 解决:742 题目描述: 统计一个数字在排序数组中出现的次数. 输入: 每个测试案例包括两行: 第一行有1个整数n,表示数组的大小. ...
- Linux安装python3.7.2详细操作步骤
1.下载Python依赖环境 yum install gcc patch libffi-devel python-devel zlib-devel bzip2-devel openssl-devel ...
- Java基础教程:反射基础
Java基础教程:反射基础 引入反射 反射是什么 能够动态分析类能力的程序称为反射. 反射是一种很强大且复杂的机制. Class类 在程序运行期间,Java运行时系统始终为所有对象维护一个被称为运行时 ...