Hibernate初级学习总结
1.Hibernate是基于是么原因产生的?(Hibernate的有点)
答案:实现业务逻辑的代码和数据库访问代码掺杂在一起,使程序结构不清晰,可读性差
在程序代码中嵌入面向关系的SQL语句,使开发人员不能完全运用面向对象的思维来编写程序
业务逻辑和关系数据模型绑定,如果关系数据模型发生变化,例如修改了CUSTOMERS表的结构,那么必须手工修改程序代码中所有相关的SQL语句,这增加了维护软件的难度
如果程序代码中的SQL语句包含语法错误,在编译时不能检查这种错误,只有在运行时才能发现这种错误,这增加了调试程序的难度
2.Hibernate是什么?
它是连接Java应用程序和关系数据库的中间件
它对JDBC API进行了封装,负责Java对象的持久化
在分层软件体系结构中它位于持久化层,封装了所有数据访问细节,使业务逻辑层可以专注于实现业务逻辑
它是一种ORM映射工具,能够建立面向对象的域模型和关系数据模型之间的映射3.hibernate中进行DML数据库操作时当注意的事项!
Public void insertUser(User user){
Configuration cfg = new Configuration().configure();
SessionFactory sf = cfg.buildSessionFactory();
Session s = sf.openSession();
Transaction tx = s.beginTransaction();
//Transaction tx = s.getTransaction(); tx.beigin();
s.save(user);
https://www.doczj.com/doc/0c12322565.html,mit();
}
1).Configuration------这个对象是用来解析和读取hibernate配置文件的对象,进一
创建hibernate上下文对象sessionFactory启动hibernate框架。
.configure()有了这个方法,程序就会自动去src根目录找所需要的配置文件。
2).SessionFactory----这是一个重量级的对象,它的创建将会使hibernate框架启动,进而创建Session对象,数据源的代理,是一个重量级的对象!如果每次都创建和销毁这样就会影响程序的运行效率,所以要单独的写在一个工具类当中,hibernae已经为我们写好了这个工具类,就是hibernateSessionFactory.java 这个工具类。
3)。Hibernate中要求必须要进行事物的控制才能正确的操作数据库,即没有自动提交。基于Session下创建的Transaction这个对象进行事物的控制。
3)。这里如果数据提交失败的话那它怎么没有数据回滚的操作呢?这里就要注意:其实hibernate已经在save()这个函数内帮我们做了try 和catch进行了数据的回滚操作,即hibernate处理异常的方式是运行时异常 RuntimenException。
4.Hibernate中复合主键的配置-------多个字段合起来构成一个主键
当没有代理主键时,采用多个自然主键来做主键
两种映射方式:直接映射和间接映射
Demo3
直接法:
user.hbm.xml 中配置如下:
间接法:
Class UsrPk{
String name;
Long phone;
}
Class User{
UserPk id;
}
User u = new User();
UserPk id = new UserPk();
id.setName(“bbb”);
id.setPhone(“13242847”);
u.setId(id);
user.hbm.xml 中配置如下:
4.Hibernate 的映射类型有那些?
Hibernate的映射类型是Java类型于SQL类型之间的桥梁
通过type属性来设置(如id和property)
Hibernate的映射类型分为两种:内置的映射类型;客户化的映射类型
客户化的映射类型通过UserType和CompositeUserType接口来实现的
1)Hibernate对java基本类型的映射参照表:
2)Hibernate对Java日期时间类型的映射
建议使用下面红颜色标示的接口:
3)Hibernate对Java大对象的映射(续)
Java中使用String来表示长字符串,使用byte[]来存放二进制数据 JDBC提供Clob和Blob类型
Character Large Object和Binary Large Object
操作大对象的方法举例
Hibernate对java大对象的映射举例:
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Customer c = new Customer();
c.setDescription(Hibernate.createClob(“”));
session.save(c);
session.flush();
sbbbbbbbbbbbbbbbfffffffffffffffffffffession.refresh(customer,LockMode.UPGR ADE);
Oracle.sql.CLOB CLOB = (Oracle.sql.CLOB)customer.getDescription();
Writer pw = clob.getCharacterOutputStream();
Pw.write(longText);
Pw.close();
https://www.doczj.com/doc/0c12322565.html,mit();
Session.close();
Hibernate中级学习总结
第一天关联关系的一对多学习
1.理解类的关联关系以及关联的方向。
一个客户可以发出多个订单;一个订单只属于一个客户
方向性是什么含义?
在关系模型中,只存在外键参照关系。而且是many方参照one方
数据库只支持一对一和一对多的单向关联关系
1-n: 一对多
user(id,name,birth)
order(id,price,user_id)
1)。单向的多对一:从订单到用户的单向多对一
class User
{
}
Class Order
{
User user;
}
在order.hbm.xml文件中配置如下结点:
作用:查询订单主对象的时候,关联的对象User也会被Hibernate自动的检索出来。
2)。单行的一对多:从用户到订单的单向一对多。
Class User
{
Set
}
Calss Order
{
}
在user.hbm.xml文件中配置如下结点:
作用:在查询用户主对象的时候,关联的对象Order集合也会被自动的检索出来。注意检索出来的Order是一个Set集合需要用迭代器将其遍历出来
代码:Iterator
While(it.hasNext)
{
Order o = it.next();
System.out.println(o.getId()+”\t” + o.getPrice());
}
3).双向的一对多
class User
{
Set
}
Class Order
{
User user;
}
配置了双向的关联关系,那么程序无法去确认谁是主动方,就会生成额外的更新语句降低程序的运行效率。这就要去告诉hibernate谁是主动方!即那个对象去操作那个对象即利用订单去控制用户!订单作为主动方的话每个订单都有一个共同的用户。在开发中应该站在多方的一边去操作一方,所以就需要的一方的配置文件中加入inverse=”true”告诉hibernate我不是主动方,就可以了!
一方配置如下:
在user.hbm.xml文件中配置如下结点:
在order.hbm.xml文件中配置如下结点:
column=”User_id”>
作用:以User作为主对象查询的时候,关联的对象Order对象也会被查询出来。
以Order作为主对象查询的时候,关联的对象User对象也会被检索出来。
5.考虑:能不能在程序中写一个基类把所有对数据库操作的通用方法写在这个基类中,而
子类内面只写一些高级不能在基类中实现的操作方法?
Class BaseDaoImpl
{
Public void insert(Object obj)
{
s.save(obj);
//jdbc
Try
{
//映射的问题。
}
}
6.Session问题:
一次请求响应用的都是同一个Session对象!
7.Hibernate中的一对一的关联关系:
1-1: 一对一
用户----账号(一对一:一个用户只有一个帐户,一个帐户只能属于每一个人)
Count(id,price,cust_id(unique))
Cust(id,name,birth)
Class Cust
{
Count count;
}
Class count
{
Cust cust;
}
注意:不要在类中构建实例,只要声明变量就可以了,以防止死循环的产生!
在Count.hbm.xml中配置:
在Cust.hbm.xml中配置:
完成以上的练习。
7.hibernate中的多对多的关联关系:
n-n: 多对多
(单向多对多/双向多对多)
商品-----商品类别(一种商品可以属于多种的商品类别,一种商品类别可以包含多中商品)
商品表:item(id,name,price)
中间表:item_cate(item_id,cate_id)
商品类别表:cate(id,name)
Class Item
{
Id;
Name;
Price;
Set
}
Class Cate
{
Id;
Name;
Set
}
请看如下的配置多对多的映射关系:
在Item.hbm.xml中配置:
在Cate.hbm.xml中配置:
完成上面的练习。
8.对象的持久化状态:hibernate中的缓存:1)一级缓存 2)二级缓存
一级缓存:内置缓存 Session缓存–---是必须用的!
缓存的工作的底层原理:
执行session.save(c1) 这个过程中:
Session下的save函数会把c1这个对象做一个快照(snapshot),然后它会生成SQL 语句把c1这个对象插入到数据库进行持久化,紧接着session下面的函数save会把c1的原对象扔到hibernate的一级缓存当中。
快照的含义:在save函数中通过克隆的技术反射出这个java对象并且将它存放到
session下List
一级缓存:在session类下又做了一个成员变量List它把插入数据库的这个对象c1掉一个list.add(c1);把c1缓存起来!
通过代码的模拟如下:
class Session
{
private List list = new ArrayList();
private List snapList = new ArrayList();
public void save(Object obj)
{
//首先做一个快照
Object objClone = obj.clone();
snapList.add(objClone);
//接着生成SQL语句将数据持久化到数据库
Inser into(。。。。。);
//然后将原对象保存到一级缓存当中。
list.add(obj);
}
}
当利用Session对数据进行持久化DML操作的时候一级缓存就被启用了!
缓存的含义:
Customer c1=new Customer(“Tom”,new HashSet());
session.save(c1);
Long id=c1.getId();
c1=null;//但垃圾回收不会回收c1这个对象,因为它在hibernate的一级缓存当中已经不属于JVM垃圾回收机制的管理了了。
Customer c2=(Customer)session.load(Customer.class,id);
//load方法去做数据库的查询操作,首先它会去一级缓存当中找id并且将这个对象查询出来,若一级缓存没有他才去数据库当中查询,并且查询出来的对象也会放在一级缓存当中!。
所以说一级缓存的做用就是为了减少访问数据库的频率,使内存的操作速度快
https://www.doczj.com/doc/0c12322565.html,mit();
session.close();
Session缓存的声明周期是很短暂的:session.close()缓存就会失效-----这个过程叫做缓存清空:
在这个过程当中hibernate会把一级缓存当中的java对象和它记录的这个快照之中的成员变量挨个的进行一个对比如果发生变化,它就会自动的生成Update语句将数据做个更新然后存放到数据库当中。例如原来快照中存放的人名叫张三,执行完了session.save(c1);这条语句,紧接着又执行 c1.setName(“LiSi”);这个时候一级缓存(内存)当中的人名变成了LiSi 在清理缓存的时候,hibernate会将一级缓存中的java成员变量和快照中对象的成员变量做个比较---把zhangsan更新为lisi持久化到数据库.
;
Session缓存的做用:
减少访问数据库的频率;(内存操作的速度快)
保证缓存中的对象与数据库中的相关记录保持同步。当持久化对象的状态发生改变,Session并不会立即执行相关的SQL语句,这使得Session可以把几条相关的SQL合并为一条,来减少访问数据库的次数。
Session加载对象时,会为对象做一个快照,当清理缓存时,会与这个备份进行比较,来决定做什么样的数据库操作。
Session是么时候清理缓存?
程序调用Transaction的commit()方法时,commit()方法先清理缓存,在提交数据库的事务
程序调用session的find()或者iterate()时,如果缓存中的持久化对象的状态发生了变化,就会先清理缓存,保证查询结果能反映持久化对象的最新状态
当应用程序显示的调用Session的flush()方法时
Hibernate应用中java对象的状态
临时状态(Transient):也叫瞬时状态。new出来的对象,没有被持久化处理,不处于Session缓存中的对象
持久化状态(Persistent):已经被持久化,加入到Session的缓存中
游离状态(Detached):也叫脱管状态。已经被持久化,但是不处在Session缓存中例如下面的代码:
Customer c1=new Customer(“Tom”,new HashSet());//c1---临时状态
session.save(c1);
Long id=c1.getId();//c1------持久化
c1=null;
Customer c2=(Customer)session.load(Customer.class,id);
//c2-----持久化(从一级缓存当中查询出来的对象)
https://www.doczj.com/doc/0c12322565.html,mit();
session.close();
System.out.println(c2.getName());
//c2-----游离状态(session都关闭了)
c2=null;
总结:
从上面的程序可以看出,Session的save方法会使得Java对象的状态转变成持久化状态;Session的close方法会使得Java对象的状态转变为游离状态;
只要处于临时状态和游离状态的Java对象不再被任何变量引用,其就结束了其生命周期;但是处于持久化状态对象不然,由于缓存还在引用这个对象,所以其还处于生命周期
临时对象的特征:
不处于Session缓存中(不被任何一个Session实例关联)
在数据库中没有对应的记录
进入临时状态的条件:
new一个Java对象,他处于临时状态,不和数据库有任何记录关联
Session的delete方法能够使一个持久化对象或游离对象转变为临时状态;对于游离对象,delete方法从数据库中删除与它对应的记录;对于持久化对象,delete方法从数据库中删除与它对应的记录,并把它从session缓存中删除
持久化对象的特征:
在一个Session实例的缓存中(与一个Session关联)
持久化对象和数据库中的相关记录对应
Session清理缓存时,会根据持久化对象的属性变化,来同步更新数据库
进入持久化状态的条件
?session的save方法
?session的load和get方法返回的对象都是处于持久化状态
?session的find方法返回的List中存在的对象都是处于持久化状态
?session的update、saveOrUpdate和lock方法使得游离对象转换为持久化状态
?当一个持久化对象关联一个临时对象,在允许级联保存的情况下,Session 在清理缓存时把这个对象也转变为持久化状态
游离对象的特征:
不再位于session缓存中(游离对象不被Session关联)
游离对象是从持久化对象转变过来的,因此在数据库中可能还存在与其对应的记录 游离对象与临时对象的区别在于:前者是由持久化对象转变过来的,并且在数据库中还存在与之对应的记录,而后者在数据库中没有与之对应的记录;
进入游离状态的条件
?当调用session的close方法的时候,session缓存被清空,缓存中的所有
持久化对象都变为游离状态。如果此时再没有其它变量引用的时候,其生命周期结束?session的evict方法能够从缓存中删除一个持久化对象,使它变为游离状态。如果内存中存在大量的对象的时候,可以通过这个方法来删除缓存中的对象(不建议使用这个方法,还是使用查询的方法和常规方法来处理对象在内存中的深度)
比较一下,下面的两个程序之间有是么区别?
Customer c=new Custoemr();
c.setName(“tom”);
session.save(c);
https://www.doczj.com/doc/0c12322565.html,mit();
Customer c=new Custoemr();
session.save(c);
c.setName(“tom”);
https://www.doczj.com/doc/0c12322565.html,mit();
以上两段对数据库的操作,虽然完成相同的功能,但是,生成的SQL语句却不同。
第一个生成一条insert语句,将customer对象存储到数据库中;而第二段代码生成两条SQL语句,一条insert和一条update
总结:
对象的OID来维持对象和数据库记录之间的对应关系。当Customer对象处于持久化状态的时候,不允许改变OID的值。
Customer c=new Customer();
session.save(c);
c.setId(new Long(6));//HibernateException
session的save方法是用来持久化一个临时对象,程序中不应该把持久化对象和游离对象传给save方法(多余的操作)
Session的update方法
使一个游离对象转变成持久化对象
把对象重新加入到缓存中,使它变为持久化对象;计划执行update语句,在清空缓存的时候真正的执行SQL
class的select-before-update属性;如果想要session仅仅在对象的属性发生变化的时候才执行update,可以把这个属性设置为true;但是这个属性会在执行update操作之间,执行一个select操作(这样会对数据库多一次查询操作,所以要根据需求来选用这个属性)
Session的saveOrUpdate方法
包含了save和update方法的功能,如果传入的参数是临时对象,就调用save方法;
如果传入是游离状态,就调用update方法;如果传入的对象是持久化对象,就直接返回;
Hibernate判断临时对象的标准:
?Java的OID取值为null
?Java对象具有version属性,并取值为null
?映射配置文件id元素设置了unsaved-value属性,并且OID的取值与unsaved-value取值匹配
?自定义了Hibernate的Interceptor实现类,并且Interceptor的isUnsaved 方法返回Boolean.TRUE
分析以下的程序
//s1持久化c1对象
Session s2=sessionFactory.openSession();
Transaction t2=s2.beginTransaction();
Customer c2=new Custoemr();
c2.setName(“Tom”);
s2.saveOrUpdate(c1);
s2.saveOrUpdate(c2);
https://www.doczj.com/doc/0c12322565.html,mit();
s2.close();
如果Customer的id的属性为Long,那么如果id为null,那么session就会判断出Customer对象为游离状态;如果id的属性为long,它的默认值为0,就需要显示的设置id的unsaved-value属性
如果Customer的id取值为0,那么就是临时对象
Session的load和get方法
load和get方法都是根据OID的值,从数据库中加载一个持久化对象
两者的区别:如果数据库中没有与给定的OID值对应的记录,load方法就会抛出异常,而get方法只是返回null
load、get方法或其它查询方法返回的对象都在session的缓存中。所以如果修改对象的属性,那么session在清理缓存后,会将数据同步到数据库
Session的delete方法
delete方法从数据库中删除与Java对象对应的记录
如果传入的参数是持久化对象,那么session计划执行一个delete语句;如果传入的参数是游离对象,那么会先把这个游离对象转化为持久化对象,然后计划执行一
个delete语句;
只有当session清理缓存时,才会真正执行delete语句;只有当session调用close 方法时,才会从session缓存中删除该对象
当调用这样的API:
List l=session.find(“from Customer as c”);的时候session中的对象是什么样子的?
8.Hibernate中的检索策略(重点需要总结)
9.利用hibernate进行分页:Hql方式和Criteria方式(重点) Hql方式:
真分页:
第一步:准备分页Page域实体:
Class Page
{
Private int currentPage;
Private int totalPage;
Private List list;
//给他们提供get 和set方法
}
第二步:确定每页要显示多少条数据。用一个抽象的类来做:
Public abstract class Constants
{
//假定设为每页显示三条数据
Public static final int = 3;
}
注意:BaseDao --------BaseDaoImpl
UserDao --------UserDaoImpl
BaseDaoImpl是BaseDao的实现类.UserDaoImpl是UserDao的实现类.
UserDao继承自BaseDao UserDaoImpl继承自BaseDaoImpl
第三步:在BaseDao接口中写如下方法:
HQL方式应注意事项:利用Query接口进行分页查询
Public Page findByPageWithHql(String hql,int currentPage);
1.传入的SQL语句是:from User where u.id=…and https://www.doczj.com/doc/0c12322565.html,=…也就是查询的条件,子类中可以根据传入的条件查处拼接SQL语句查询所需要的数据。
2.并且传入当前是第几页,以便子类利用查出当前页的所有数据
Public interface BaseDao
{
Public Page findByPageWithHql(String hql,int currentPage);
Public Page findByPageWithCriteria(DetachedCriteria c,int currentPage); }
利用Criteria接口进行查询应注意的事项:
Public Page findByPageWithCriteria(DetachedCriteria c,int currentPage);
1.Criteria是面向对象的方式进行查询的,所以传入的第一个参数就需要的是一个对象,
那么在这里是么对象进去,可以传入一个User对象进去,然后就可以根据user对象的引用得到其中的成员变量,以便在Criteria接口中提供查询的条件,但这样这个接口就被限制的太死了,其他的用户例如order对象就不能使用了,那怎么办呢,其实在这里只要传入Criteria对象本身就可以了,一位Criteria接口本身就带有条件即c.add();
这样的功能.但是若传入Criteria接口由于它是处于持久化状态和session对象紧紧的绑定在一起,若对它操作的话就会引起数据库的更新操作使程序的效率大大的降低,解决这个问题的方法:hibernate已经为我们做了一个游离状态的Criteria对象它就是DetachedCriteria这个对象:利用它就可以进行查询的操作!
第四步:写出BaseDao这个接口的实现类
Public class BaseDaoImpl
{
Protected Class clazz; //注意这是为了在子类中可以根据构造方法接收到传入的类。
//hql已是子类(继承它的子类,例如第五步中拼接的SQL语句)中封装好的SQL 语句传进来的高级查询的条件
// select https://www.doczj.com/doc/0c12322565.html, … from User u where u.id = …….and …..
Public Page findByPageWithHql(String hql,int currentPage)
{
//注意无论写是么函数首先要确定这个函数要完成是么功能:
//当前的函数需要完成三个共能:1 求出当前是第几页并将其set到p对象中//2.计算出当前的总页数并将其set到p中返回
//3.查询出符合条件的结果将其set到list中返回到p对象中。
Session s = HibernateSessionFactory.getSession();
Page p = new Page();
p.setCurrentPage(currentPage);
//totalPage计算数据库中存储的数据库的总条数
//由于传进来的SQL语句hql很能是select https://www.doczj.com/doc/0c12322565.html, …from User u where u.id = …….and …或者from User u where u.id = …….and …..但在我们的
hibenate中select …和from前面的这些需要在下面的程序中去投影,所以
传过来的select….和from关键字就是多余的了这样就会引起SQL语句的
不能正确执行的异常(unexpected token)。为了解决这个问题,我们在需
要把传进来的hql SQL语句按着关键子from进行拆分得到一个数据抽取数组
中的第二个元素,就是我们hibernate中将要执行的hql语句,代码如下: String[] str = hql.split(“from”);
//String countHql = “select count(*) from”(“+ hql +”)”;这样会处错误的!需要注意。
String countHql = “select count(*) from” + str[1];
//创建Query查询对象.查询数据库中数据的总条数
Query countQ = s.createQuery(countHql);
Int toatalNum = 1;//默认总条数为1
//注意一般无论是Query对象还是 Criteria对象查出来的列大于一的时候//他们返回的都是数组,只有当查出来的结果是一列的时候就可以调
//uniqueResult()函数查询出结果并且可以将结果转换成任意类型的数据。
// 注意这里还涉及到类型转化问题,在HQL这种方式下返回来的结果是Long
型的如果需要的是整形的话就进行如下的转换就可以了
//totalNum = (Long)countQ.uniqueResult()
totalNum = ((Long)countQ.uniqueResult()).intValu();
//根据查询到的总条数和常量类中规定每页将要显示的条数计算出总页数
Int totalPage = 1;
If(totalNum%Constants.ITEM_PER_PAGE==0)
{
totalPage = totalNum/Constants.ITEM_PER_PAGE;
}else{
totalPage = totalNum/Constants.ITEM_PER_PAGE + 1;
}
p.setTotalPage(totalPage);
//再一次的创建另一个Query查询当前页中将要显示的数据,hibernate 中//为我们做了分页的函数只要告诉它当前页将从数据库中的第几条开始查
//到多少条结束,并将结果返回。Hibenate是面向对象的所以是从0开始
//的不象JDBC中是从1开始的
Int from = (currentPage - 1) * Constants.ITEM_PER_PAGE;
Query findQ = s.cretatQuery(hql);
Findq.setFirstResult(from);
Findq.setMaxResults(Constants.ITEM_PER_PAGE);
List list = findQ.list();
p.setList(list);
return p;
}
Public Page findByPageWithCriteria(DetachedCriteria c,int currentPage)
{
Session s = HibernateSessionFactory.getSession();
Page p = new Page();
p.setCurrentPage(currentPage);
//计算 totalPage
//Criteria 中的投影操作用的是Projection和projections
c.setProjection(Projections.rowCount());
//注意我们传进来的DetachedCriteria是一个处于游离状态的对象,它要被
//hibernate利用session操作数据库话就必须将其转化成一个可执行的
//Criteria对象并且将其绑定session存放到一级缓存当中。变成可运行的
//状态
Criteria countC = c.getExcutableCriteria(s);
Int totalNum = 1;
totalNum = (Integer)countC.uniqueResult();
int totalPage = 1;
if(totalNum%Constants.ITEM_PER_PAGE==0)
{
totalPage = totalNum/Constants.ITEM_PER_PAGE;
}else{
totalPage = totalNum/Constants.ITEM_PER_PAGE + 1;
}
p.setTotalPage(totalPage);
//result
//在这里需要注意:在最后查询结果这里的时候又要用到Criteria这个接口,由
于在上面第一次经过了c.setProjection(Projections.rowCount())投影
操,使得c中的内容变成了select count(*) from ...where .......下面
我们需要的是 from ....where......所以就要即那个c置为空,然后再去让它
变成可执的,还可以重新的去做投影。
c.setProjection(null);
Criteria findC = c.getExcutableCriteria(s);
Int from = (currentPage-1) * Constants.ITEM_PER_PAGE;
findC.setFirstResult(from);
findC.setMaxResults(Constant.ITEM_PER_PAGE);
List list = findC.list();
p.setList(list);
return p;
}
}
上面程序当中需要的hql条件语句就是在如下的子类当中拼接成的,请看如下代码:第五步:在UserDao接口中写实现这两种方式的方法:
注意这里传入的参数user 对象就是在action当中封装好的user传给Dao的
Public interface UserDao extends BaseDao
{
public Page findUserByPropertyWithPage(User user,int currentPage);
public Page findUserByProperyWithPageUsingCriteria(User user,int currentPage);
}
第六步:在UserDao的实现类UserDaoImpl中根据action当中传入的对象取其中的条件进行拼接超类BaseDaoImpl当中所需要的SQL语句以便它进行分页查询返回Page结果:Public class UserDaoImpl extends BaseDaoImpl
HQL方式代码如下:Query
public Page findUserByPropertyWithPage(User user, int currentPage) {
//拼接超类当中所需要的SQL语句-----from User u where
u.id=.......and .......
StringBuffer s = new StringBuffer("from User u where 1=1");
if(user.getId() != null && user.getId()>0){
s.append(" and u.Id=").append(user.getId());
}
if(user.getName() != null && user.getName().length()>0){ s.append(" and https://www.doczj.com/doc/0c12322565.html, like
'").append(user.getName()).append("%'");
}
if(user.getBirth() != null){
s.append(" and
u.Birth='").append(user.getBirth()).append("'");
}
return findByPageWithHql(s.toString(), currentPage);
}
@Override
//Criteria接口的方式:
public Page findUserByProperyWithPageUsingCriteria(User user,
int currentPage) {
DetachedCriteria c = DetachedCriteria.forClass(User.class);
if(user.getId() != null && user.getId()>0){
c.add(Restrictions.eq("id", user.getId()));
}
if(user.getName() != null && user.getName().length()>0){
c.add(Restrictions.like("name", "%"+user.getName()+"%"));
}
if(user.getBirth() != null){
c.add(Restrictions.like("birth", user.getBirth()));
}
return findByPageWithCriteria(c, currentPage);
}
}
第七步写一个main方法模拟action进行测试:
public class Test5 {
//测试HQL大分页方式;
public static void main(String[] args){
User u = new User();
Page p = new UserDaoImpl().findUserByPropertyWithPage(u, 2);
System.out.println("当前是第"+ p.getCurrentPage() +" 页,一共有"+ p.getTotalPage()+"页");
for(int i=0;i
User user = (User)p.getList().get(i);
System.out.println(u.getId() + "\t" + u.getName() +"\t" + u.getBirth());
}
//测试Criteria的方式
User u = new User();
Page p = new UserDaoImpl().findUserByPropertyWithPage(u, 4);
System.out.println("当前是第" +p.getCurrentPage()+"页,一共有" + p.getTotalPage()+"页");
for(int i=0;i
User user = (User)p.getList().get(i);
System.out.println(u.getId() + "\t" + u.getName() + "\t" + u.getBirth());
}
}
}