Hibernate框架基础
概述
Hibernate框架是持久层的框架,让我们只需在框架配置文件中配置驱动、数据库用户、密码、需要连接的数据库名等就可以连接Mysql、Oracle等就可以自动连接、访问数据库,不需要再用JDBC,方便项目的移植。Hibernate可以通过映射文件(后缀为.hbm.xml)配置表与对象的映射关系,因此可以通过此框架我们可以方便地通过操作对象的方式来增删查改数据库。
Hibernate至少需要的jar包
其中mysql-connector-java-5.1.46.jar是Mysql数据库的驱动,不同的数据库用不同的驱动
Hibernate框架总配置文件
默认的总配置文件是在src文件夹下的hibernate.cfg.xml。(eclipse在编译时会表src下的xml文件放到字节码文件所在目录)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property><!--不同数据库用不同驱动-->
<property name="connection.url">
jdbc:mysql://localhost:3306/要连接的数据库
</property>
<property name="connection.username">root</property>
<property name="connection.password">这里写密码</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hbm2ddl.auto">update</property><!--加载时自动根据映射文件更新表结构-->
<property name="hibernate.show_sql">true</property><!--调试时输出sql执行语句-->
<mapping resource="t/Test.hbm.xml"/><!--映射文件位置-->
</session-factory>
</hibernate-configuration>
在连接的数据库应该事先建好,但表不用建。
property name="hbm2ddl.auto"标签值为update表示hibernate启动时根据映射文件更新数据库,原来的列不会删除。
持久化对象
先说一下术语
PO:持久化对象,与数据库的一张表对应,其中的属性对应表各个列(字段)的数据类型。
VO:持久化视图对象,与数据库的一张视图对应,其中的属性对应视图各个列的数据类型。
以上对象一般都是JavaBean,JavaBean的规范是属性应是private,再分别设置public的setter和getter方法。
类需要对应的映射文件才能与数据库的表或视图产生关系。
Hibernate映射文件
后缀为.hbm.xml,一般与对应的类文件放在一起,文件名一般与对应的类名相同,映射文件需要在总配置文件中指定其位置才能被框架读取。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 注意包名。不写的话下面要写全限定名 -->
<hibernate-mapping package="t">
<!-- 类名对应表名 -->
<class name="Test">
<!-- 主键使用id标签。然后对应属性名与列名 -->
<id name="id" type="int" column="id">
<!-- 自增长主键不同数据库有不同类型的自增长类型 -->
<generator class="increment"></generator>
</id>
<!-- 非主键映射关系,注意类型并不是单纯的java类型也不是数据库类型,而是一种hibernate中间类型,注意大小写特别是String在这里开头要小写 -->
<property name="t" type="string"/>
</class>
</hibernate-mapping>
generator class="increment"表示自增长方式生成主键,native表示让框架自动决定主键生成策略。
如果主键由用户指定,则不配置generator标签。
Hibernate,Java,SQL映射关系
【1】常见的映射关系表
Hibernate映射类型 | Java类型 | 标准SQL类型 | 字节大小 |
---|---|---|---|
integer/int | java.lang.Integer/int | INTEGER | 4Byte |
long | java.lang.Long/long | BIGINT | 8Byte |
short | java.lang.Short/short | SMALLINT | 2Byte |
byte | java.lang.Byte/byte | TINYINT | 1Byte |
float | java.lang.Float/float | FLOAT | 4Byte |
double | java.lang.Double/double | DOUBLE | 8Byte |
big_decimal | java.math.BigDecimal | NUMERIC | |
character | java.lang.Character/java.lang.String/char | CHAR | 定长字符 |
string | java.lang.String | VARCHAR | 变长字符 |
boolean/yes_no/true_false | java.lang.Boolean/boolean | BIT | 布尔类型 |
date | java.util.Date/java.sql.Date | DATE | 日期 |
time | java.util.Date/java.sql.Time | TIME | 时间 |
timestamp | java.util.Date/java.util.Timestamp | TIMESTAMP | 日期 |
calendar | java.util.Calendar | TIMESTAMP | 日期 |
calendar_dar | java.util.Calendar | DATE | 日期 |
binary | byte[] | BLOB | BLOB |
text | java.lang.String | CLOB | CLOB |
serializable | 实现java.io.Serializable接口的任意Java类 | BLOB | BLOB |
clob | java.sql.Clob | CLOB | CLOB |
blob | java.sql.Blob | BLOB | BLOB |
class | java.lang.Class | VARCHAR | 定长字符 |
locale | java.util.Locale | VARCHAR | 定长字符 |
timezone | java.util.TimeZone | VARCHAR | 定长字符 |
currency | java.util.Currency | VARCHAR | 定长字符 |
【2】Java时间和日期类型的Hibernate映射
映射类型 | Java类型 | 标准SQL类型 | 描述(java中表示) |
---|---|---|---|
date | java.util.Date/java.sql.Date | DATE | 日期:yyyy-MM-dd |
time | java.util.Date/java.sql.Time | TIME | 时间 :HH:mm:ss |
timestamp | java.util.Date/java.util.Timestamp | TIMESTAMP | 日期和时间:yyyy-MM-dd HH:mm:ss |
calendar | java.util.Calendar | TIMESTAMP | 同上 |
calendar_dar | java.util.Calendar | DATE | 日期:yyyy-MM-dd |
一对一、一对多、多对多的配置
对于一对多配置保证了参照完整性,对于多对多,需要新建一张表来表示他们的关系。
一对一配置
比如Person(人)和Id_Card(身份证)是一对一的关系
单向一对一外键关联
Id_Card单向依赖于Person
此方式生成的表会有外键约束,而共享主键方式则没有。
这是一种特殊的一对多关系,只是增加了一个unique属性。这样就指定了这端为一了。
Person.java:
public class Person {//与ID_Card为一对一关系
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Person.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 注意包名。不写的话下面要写全限定名 -->
<hibernate-mapping package="t">
<class name="Person">
<id name="id" type="int" column="id">
<generator class="native"></generator>
</id>
<property name="name" type="string"/>
</class>
</hibernate-mapping>
Id_Card.java:
public class Id_Card {//与Person是一对一关系
private int id;
private String cardNum;
private Person person;//指定其对应的Person
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCardNum() {
return cardNum;
}
public void setCardNum(String cardNum) {
this.cardNum = cardNum;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
}
Id_Card.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 注意包名。不写的话下面要写全限定名 -->
<hibernate-mapping package="t">
<class name="Id_Card">
<id name="id" type="int" column="id">
<generator class="increment"></generator>
</id>
<property name="cardNum" type="string"/>
<!--跟多对一一样,只是增加了一个unique属性。这样就指定了这端为一了。-->
<many-to-one name="person" class="Person" column="pid" unique="true"></many-to-one>
</class>
</hibernate-mapping>
插入记录:
Person person=new Person();
Id_Card id_Card=new Id_Card();
id_Card.setPerson(person);
session.save(person);
session.save(id_Card);
单向共享主键方式(推荐)
Id_Card单向依赖于Person,表示在插入Id_Card记录时必须先指明对应的Person。
此方式生成的表没有外键约束
其实用框架访问数据库的话没有外键约束也没什么影响
Person.java:
public class Person {//与ID_Card为一对一关系
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Person.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 注意包名。不写的话下面要写全限定名 -->
<hibernate-mapping package="t">
<class name="Person">
<id name="id" type="int" column="id">
<generator class="native"></generator>
</id>
<property name="name" type="string"/>
</class>
</hibernate-mapping>
Id_Card.java:
public class Id_Card {//与Person是一对一关系
private int id;
private String cardNum;
private Person person;//指定其对应的Person
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCardNum() {
return cardNum;
}
public void setCardNum(String cardNum) {
this.cardNum = cardNum;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
}
Id_Card.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 注意包名。不写的话下面要写全限定名 -->
<hibernate-mapping package="t">
<class name="Id_Card">
<id name="id" type="int" column="id">
<!-- 指定id为外键 -->
<generator class="foreign">
<param name="property" >person</param><!-- 外键指向person属性 -->
</generator>
</id>
<property name="cardNum" type="string"/>
<!-- name指定属性名,class指定类名 -->
<one-to-one name="person" class="Person"></one-to-one>
</class>
</hibernate-mapping>
表结构:
person表
id_card表
插入Person和Id_Card记录:
Person person=new Person();
Id_Card id_Card=new Id_Card();
id_Card.setPerson(person);//指定对应的person
session.save(person);
session.save(id_Card);
在插入id_Card前需要指定对应的person才能插入成功
插入成功:
双向共享主键方式
双向共享方式在插入一条Person记录前必须指定对应的Id_Card,在插入Id_Card前必须指定对应的Person
Person:
public class Person {//与ID_Card为一对一关系
private int id;
private String name;
private Id_Card id_Card;//指定对应的ID_Card
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Id_Card getId_Card() {
return id_Card;
}
public void setId_Card(Id_Card id_Card) {
this.id_Card = id_Card;
}
}
Person.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 注意包名。不写的话下面要写全限定名 -->
<hibernate-mapping package="t">
<class name="Person">
<id name="id" type="int" column="id">
<generator class="native"></generator>
</id>
<property name="name" type="string"/>
<!-- name指定属性名,class指定类名 -->
<one-to-one name="id_Card" class="Id_Card"></one-to-one>
</class>
</hibernate-mapping>
Id_Card:
public class Id_Card {//与Person是一对一关系
private int id;
private String cardNum;
private Person person;//指定其对应的Person
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCardNum() {
return cardNum;
}
public void setCardNum(String cardNum) {
this.cardNum = cardNum;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
}
Id_Card.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 注意包名。不写的话下面要写全限定名 -->
<hibernate-mapping package="t">
<class name="Id_Card">
<id name="id" type="int" column="id">
<!-- 指定id为外键 -->
<generator class="foreign">
<param name="property" >person</param><!-- 外键指向person属性 -->
</generator>
</id>
<property name="cardNum" type="string"/>
<!-- name指定属性名,class指定类名 -->
<one-to-one name="person" class="Person"></one-to-one>
</class>
</hibernate-mapping>
插入Person和Id_Card记录:
Person person=new Person();
Id_Card id_Card=new Id_Card();
person.setId_Card(id_Card);//指定对应的id_Card
id_Card.setPerson(person);//指定对应的person
session.save(person);
session.save(id_Card);
双向共享主键方式在插入前需要分别指定对应的id_Card、person才能被插入
插入成功:
一对多配置
比如Class(班级)和Student(学生)是一对多关系
生成的学生表中有一个外键指向班级的主键,以标识学生属于哪个班级
新建Class类:
Class.java:
public class Class {//与Student是一对多关系
private int cid;
private String cname;
//用集合表示班级包含了哪些学生
private Set<Student> students = new HashSet<Student>();
public Set<Student> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = students;
}
public int getCid() {
return cid;
}
public void setCid(int cid) {
this.cid = cid;
}
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
}
新建Student类:
public class Student {//与Class是多对一的关系
private String sno;//主键
private String sname;
//指定学生属于哪个班级
private Class class1;
public String getSno() {
return sno;
}
public void setSno(String sno) {
this.sno = sno;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public Class getClass1() {
return class1;
}
public void setClass1(Class class1) {
this.class1 = class1;
}
}
Class类配置文件:
Class.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 注意包名。不写的话下面要写全限定名 -->
<hibernate-mapping package="t">
<!--一,主键属性 -->
<class name="Class">
<id name="cid" type="int" column="cid">
<generator class="native"></generator>
</id>
<!-- 二,其它属性 -->
<property name="cname" type="string"/>
<!-- 三,集合属性,表示和学生的关系 -->
<set name="students">
<!--3.2 生成的Student表需要一个外键指向他的班级的主键,key的 column表示Student表的外键名 -->
<key column="cid"/>
<!--3.3 one-to-many的class属性指定多方的类名 -->
<one-to-many class="Student"/>
</set>
</class>
</hibernate-mapping>
Student类配置文件:
Student.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 注意包名。不写的话下面要写全限定名 -->
<hibernate-mapping package="t">
<class name="Student">
<id name="sno" type="string" column="sno"></id><!-- 主键在插入时指定 -->
<property name="sname" type="string"/>
<!-- 表示和分类的关系 -->
<!--3.1name:一的一方对象的名字
class: 一的一方类名
column:外键的名字
-->
<many-to-one name="class1" class="Class" column="cid"/>
</class>
</hibernate-mapping>
插入班级和学生记录:
Class class1=new Class();
class1.setCname("一班");
Student student=new Student();
student.setClass1(class1);
student.setSno("001");
student.setSname("张三");
session.save(class1);
session.save(student);
插入成功:
在插入学生记录之前需要指定其班级才能插入成功。
一对多级联删除
当删除Class记录时自动删除对应的所有学生记录的外键(对应外键变成null值)
只需在Class.hbm.xml的set标签加上属性:
cascade="delete"
Class.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 注意包名。不写的话下面要写全限定名 -->
<hibernate-mapping package="t">
<!--一,主键属性 -->
<class name="Class">
<id name="cid" type="int" column="cid">
<generator class="native"></generator>
</id>
<!-- 二,其它属性 -->
<property name="cname" type="string"/>
<!-- 三,集合属性,表示和学生的关系 -->
<set name="students" cascade="delete">
<!--3.2 生成的Student表需要一个外键指向他的班级的主键,key的 column表示Student表的外键名 -->
<key column="cid"/>
<!--3.3 one-to-many的class属性指定多方的类名 -->
<one-to-many class="Student"/>
</set>
</class>
</hibernate-mapping>
Student映射文件不变
删除之前:
class表
student表
删除班级记录:
Class class1=new Class();
class1.setCid(3);
session.delete(class1);
删除后:
class表:
student表:
多对多配置
多对多关系不仅需要两种表分别描述两个实体,还要一张表来描述他们的关系。
中间表无其他属性
比如学生(Student)和课程(Course)是多对多关系s_c表描述一个学生选了哪些课程。
Student.java:
public class Student {//与Class是多对一的关系
private String sno;//主键
private String sname;
//指定学生属于哪个班级
private Class class1;
//指定学生选了哪些课
private Set<Course> courses=new HashSet<Course>();
public String getSno() {
return sno;
}
public void setSno(String sno) {
this.sno = sno;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public Class getClass1() {
return class1;
}
public void setClass1(Class class1) {
this.class1 = class1;
}
public Set<Course> getCourses() {
return courses;
}
public void setCourses(Set<Course> courses) {
this.courses = courses;
}
}
Student.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 注意包名。不写的话下面要写全限定名 -->
<hibernate-mapping package="t">
<class name="Student">
<id name="sno" type="string" column="sno"></id><!-- 主键在插入时指定 -->
<property name="sname" type="string"/>
<!-- 表示和班级的关系 -->
<!-- name:一的一方对象的名字
class: 一的一方类名
column:外键的名字
-->
<many-to-one name="class1" class="Class" column="cid"/>
<!-- 表示和课程的关系 -->
<!-- set标签的name属性:当前类中集合的名字
table:关系的表名
-->
<set name="courses" table="s_c">
<!-- key的 column表示当前类在关系表中的外键 -->
<key column="sno" />
<!--many-to-many表示多对多关系
column:表示另一方在关系表中的外键
class:表示另一方类名
-->
<many-to-many column="cno" class="Course" ></many-to-many>
</set>
</class>
</hibernate-mapping>
Course.java:
public class Course {
private String cno;
private String cname;
public String getCno() {
return cno;
}
public void setCno(String cno) {
this.cno = cno;
}
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
}
Course.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 注意包名。不写的话下面要写全限定名 -->
<hibernate-mapping package="t">
<class name="Course">
<id name="cno" type="string" column="cno"></id><!-- 主键在插入时指定 -->
<property name="cname" type="string"/>
</class>
</hibernate-mapping>
中间表有其他属性
比如学生(Student)和课程(Course)是多对多关系,成绩表描述他们之间的关系和学生每门课成绩。
学生表(学号,姓名,…)
课程表(课程编号,课程名,…)
成绩(学号,课程编号,成绩,…)
此时就要新建Student、Course、Grade类,并分别进行映射文件配置。配置Student与Grade为多对一关系,Grade与Course为一对多关系。
DAO层对数据的操作(增删查改)
生成session对象
java访问数据库通过session对象,session表示java通过hibernate与数据库的一次会话,当操作数据完成时应关闭session,以提高效率,防止内存溢出。以下是生成session对象及关闭的代码。
HibernateUtil.java:
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
private static SessionFactory sessionFactory;
private HibernateUtil() {
// TODO Auto-generated constructor stub
}
static {
Configuration cfg = new Configuration();
cfg.configure();
sessionFactory = cfg.buildSessionFactory();
}
public static Session getSession() {
Session session = sessionFactory.openSession();
return session;
}
}
通过此方法创建和关闭session,避免多线程共享数据的问题。
增加数据
- 操作对象方式增加
session = HibernateUtil.getSession();
transaction = session.beginTransaction();//事务开始
session.save(test);//增加数据
transaction.commit();//事务提交
HibernateUtil.closeSession();
test是一个持久化对象,hibernate会根据持久化对象的主键与数据库中存在的主键确定是增加还是修改.
事务提交表示原子操作完成,提交后数据不可回滚,事务操作是数据库系统提供的功能.
- 通过HQL语句实现
增加就不要用hql实现了.
修改:
tx=session.beginTransaction();
//session.save(test);
Query query=session.createQuery("update Test tt set tt.str=:utest where tt.id=:uid");
query.setParameter("utest", "aa");
query.setParameter("uid", 1);
query.executeUpdate();
tx.commit();
Test是持久化的类名,而不是表名.
HQL与SQL的一个不同就是HQL指定的是类及其对象,而SQL指定的是表和表的列.
修改数据
session = HibernateUtil.getSession();
transaction = session.beginTransaction();//事务开始
session.update(test);//修改数据
transaction.commit();//事务提交
HibernateUtil.closeSession();
删除数据
- 操作对象方式实现
Transaction transaction = null;
session = HibernateUtil.getSession();
transaction = session.beginTransaction();
session.delete(test);//删除数据
transaction.commit();
HibernateUtil.closeSession();
- 通过HQL语句删除
tx=session.beginTransaction();
Query query=session.createQuery("delete from Test tt where tt.id=:uid");
query.setParameter("uid", 1);
query.executeUpdate();//执行hql语句
tx.commit();
执行增加,删除,修改HQL语句用executeUpdate(),查询用list().
查询数据
- session通过主键查询
Test test2 = (Test) session.get(Test.class, obj);
Test是持久化对象类
obj即为要查询的主键值
- HQL语句通过条件实现查询
Query query=session.createQuery("from Test tt where tt.id=:参数");
query.setParameter("参数", obj);
List<Test> tests = query.list();
HQL可省略select.
如果没有where限定则查询所有
查询不需要事务操作.
Hibernate分页
hibernate框架的Criteria类提供了分页功能,只需要告知hibernate从哪一行开始、最大行数即可返回页面所需的数据。
实现
实现创建Page类保存当前页码、每页记录数、总页数、总记录数等信息。如果不想封装也可跳过此步。
Page.java:
public class Page {
/**
* @param perPageRows 每页行数
*/
private Integer currentPage=1;//当前页,默认为第一页
private Integer perPageRows=3;//每页的记录数,默认为3
private Integer totalRows;//总记录数:
private Integer totalPages;//总页数:
public Integer getCurrentPage() {
return currentPage;
}
public void setCurrentPage(Integer currentPage) {
this.currentPage = currentPage;
}
public Integer getPerPageRows() {
return perPageRows;
}
public void setPerPageRows(Integer perPageRows) {
this.perPageRows = perPageRows;
}
public Integer getTotalRows() {
return totalRows;
}
public void setTotalRows(Integer totalRows) {
this.totalRows = totalRows;
}
public Integer getTotalPages() {
//计算总页数
totalPages=totalRows%perPageRows==0?totalRows/perPageRows:totalRows/perPageRows+1;
return totalPages;
}
public void setTotalPages(Integer totalPages) {
this.totalPages = totalPages;
}
}
获取对应页面数据
Criteria criteria=session.createCriteria(Test.class);//设置要查询的持久化对象
//每页开始的索引数在hibernate中的计算公式是:(currentPage-1)*perPageRows
criteria.setFirstResult((currentPage-1)*perPageRows);//设置开始查找的行数
criteria.setMaxResults(perPageRows);//设置最大查找的行数
@SuppressWarnings("unchecked")
List<Test> tests = criteria.list();//获取页面数据
其中Test是持久化对象
实际开发中currentPage提供客户端的请求参数获取
以上代码一般封装在DAO层的方法中
案例(对News持久化对象的分页)
首先新建DAO类:
News.java:
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import PO.News;
public class NewsDAO {
@SuppressWarnings("unchecked")
public List<News> findAll() {
// TODO Auto-generated method stub
Session session=HibernateUtil.getSession();
List<News> news;
Query query = session.createQuery("from News");
news=query.list();
session.close();
return news;
}
/**
*
* @param currentPage 当前页码
* @param pageSize 页码大小,每页多少行数据
* @return 当前页的数据集合
*/
public List<News> findPageList(int currentPage,int pageSize){
Session session=HibernateUtil.getSession();
Criteria criteria=session.createCriteria(News.class);
criteria.setFirstResult((currentPage-1)*pageSize);
criteria.setMaxResults(pageSize);
@SuppressWarnings("unchecked")
List<News> news = criteria.list();
session.close();
return news;
}
}
显示的页面:
<%@page import="java.util.LinkedList"%>
<%@page import="java.util.List"%>
<%@page import="DAO.NewsDAO"%>
<%@page import="PO.News"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
String strc=request.getParameter("currentPage");
int currentPage,pageCount,pageSize=3;
NewsDAO newsDAO=new NewsDAO();
int rows=newsDAO.findAll().size();
pageCount=rows%pageSize==0?rows/pageSize:rows/pageSize+1;//计算总页数
if(strc==null){//设置当前页码
currentPage=1;
} else {
currentPage = Integer.parseInt(strc);
}
//System.out.print(currentPage);
List<News> news=newsDAO.findPageList(currentPage, pageSize);//获取当前页的数据
List<String> titles = new LinkedList<String>();
for(News tnews:news){
titles.add(tnews.getTitle());
}
pageContext.setAttribute("titles", titles);
pageContext.setAttribute("currentPage", currentPage);
pageContext.setAttribute("pageCount", pageCount);
%>
<c:forEach items="${titles }" var="strTi">
<div>${strTi }</div>//页码输出数据
</c:forEach>
<a href="pages.jsp?currentPage=1">第一页</a>
<c:if test="${currentPage!=1 }">
<a href="pages.jsp?currentPage=${currentPage-1 }">上一页</a>
</c:if>
<c:if test="${currentPage!=pageCount }">
<a href="pages.jsp?currentPage=${currentPage+1 }">下一页</a>
</c:if>
<a href="pages.jsp?currentPage=${pageCount }">最后页</a>
</body>
</html>