Hibernate是一种基于Java的轻量级的ORM框架
其中Mapping把Object类型的数据映射到关系型数据库中,这样就可以让我们只操作对象,不需要操作数据库。
java程序通过JDBC+SQL来操作数据库
Hibernate的出现简化了开发者手工进行数据库连接与操作数据库的步骤,帮助开发者创建数据库连接并为用户生成对应的SQL语句,降低了手工进行Java操作数据过程中的风险,一定程度上缩短了用户使用JDBC+SQL进行操作数据库的开发时间,但是底层仍然是JDBC+SQL,所以速度方面略慢。
下载网址:http://hibernate.org/orm/downloads/
搭建环境步骤:
默认位置在classpath下,默认名称hibernate.cfg.xml
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">com.jdbc.mysql.Driverproperty>
<property name="connection.url">jdbc:mysql://localhost:3306/hiber01property>
<property name="connection.username">rootproperty>
<property name="connection.password">rootproperty>
<property name="connection.pool_size">1property>
<property name="dialect">org.hibernate.dialect.MySQL5Dialectproperty>
<property name="show_sql">trueproperty>
<mapping resource=""/>
session-factory>
hibernate-configuration>
4.创建实体类(model)
public class User {
private int userId;
private String uname;
private int gender;
private Date birthday;
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public int getGender() {
return gender;
}
public void setGender(int gender) {
this.gender = gender;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
Hibernate.cfg.xml是默认的文件名称,可以随便起名xxx.xml,建议使用hibernate.cfg.xml
<property name="connection.driver_class">com.mysql.jdbc.Driverproperty>
<property name="connection.url">jdbc:mysql://localhost:3306/hiber01property>
<property name="connection.username">rootproperty>
<property name="connection.password">rootproperty>
<property name="connection.pool_size">1property>
Hibernate可以支持多种数据库,不同数据库的sql会有差别,hibernate可以根据不同的数据库来生成不同的sql,每一种数据库hibernate为我们定义了一种方言
<property name="dialect">org.hibernate.dialect.MySQL5Dialectproperty>
是否在控制台输出sql语句
<property name="show_sql">trueproperty>
<property name="c3p0.min_size">10property>
<property name="c3p0.max_size">100property>
<property name="c3p0.timeout">3000property>
<property name="hbm2ddl.auto">noneproperty>
总共有四个值:
我们默认选择none或者不配置就ok了
注意包名用/分隔
<mapping resource="com/rl/hiber/model/User.hbm.xml"/>
Hibernate中使用OID区分对象是否相同,Hibernate认为每一个不同的对象应该具有一个唯一的标识,称这个标识为OID。
Java对象中可以使用任意属性作为OID。
自然主键:具有业务含义
例如个人信息中的身份证号,不仅是唯一的,而且还具有业务含义,这种属性虽然可以做为OID,但是其具有一定的业务含义。选择OID尽量避免使用具有业务含义的属性。
代理主键:不具有业务含义
声明一个不具有任何业务含义的属性,仅用于区分对象,这种属性即便暴漏给最终用户查看,也不具有安全隐患
OID选择应尽量避免使用自然主键,改用代理主键
基本数据有一个默认值的特点,特性在对象数据封装时存在着数据隐患,一旦基本数据类型取值为默认值,开发者将无法区分该值是用户输入数据还是未输入数据由系统默认给出。
封装类数据类型可以使用是否为null来判定该数据是来自于用户输入还是未输入。
每一个model都有一个相对于的映射文件,命名规范:模型类.hbm.xml,位置可以任意但是建议放在model的同级包下。
<class name="User" table="t_user">
class:映射类
属性:
<property name="uname">property>
<property name="gender">property>
<property name="birthday">property>
Property:属性的映射
属性:
<!—id
是主键映射配置
-->
<id name="userId" column="user_id">
<generator class="assigned">generator>
id>
映射策略如下:
Hibernate: select max(user_id) from t_user
Hibernate: insert into t_user (uname, gender, birthday, user_id) values (?, ?, ?, ?)
下图如果A先插入数据库中的主键最大值就是2,B这时来插入就出现了主键重复
Increment方式有并发问题,所以不用。
create table t_user (
user_id integer not null auto_increment,
uname varchar(255),
gender integer,
birthday datetime,
primary key (user_id)
)
输出
Hibernate: insert into t_user (uname, gender, birthday) values (?, ?, ?)
这种自增没有并发问题,因为主键的自增策略由数据库管理(有锁机制)
@Test
public void test() {
//创建hibernate配置对象
Configuration cfg = new Configuration();
//配置hibernate的核心文件的位置
cfg.configure("hibernate.cfg.xml");
//注册配置属性信息
ServiceRegistry sr = new StandardServiceRegistryBuilder()
.applySettings(cfg.getProperties()).build();
//创建SessionFactory
SessionFactory factory = cfg.buildSessionFactory(sr);
//创建Session
Session session = factory.openSession();
//开启事务
Transaction tx = session.beginTransaction();
//创建对象
User user = new User();
//user.setUserId(2);
user.setUname("renliang");
user.setGender(1);
user.setBirthday(new Date());
//通过Session保存对象
session.save(user);
//提交事务
tx.commit();
session.close();
factory.close();
}
@Test
public void test2(){
Session session = HibernateUtils.getSession();
Transaction tx = session.beginTransaction();
try {
//创建对象,这时是瞬时对象
User user = new User();
user.setUname("任亮");
user.setGender(1);
user.setBirthday(new Date());
//发出sql语句,把user对象纳入到Session的管理,并且保存到数据库,持久状态
session.save(user);
//设置持久对象的属性,Session会把修改后的持久
//对象的属性值和没有修改时的做对比,如果有变化就发出update,没有就不发
user.setUname("任亮");
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtils.closeResource(session);
}
}
@Test
public void test4(){
Session session = HibernateUtils.getSession();
Transaction tx = session.beginTransaction();
User user = new User();
try {
user.setUname("任亮");
user.setGender(1);
user.setBirthday(new Date());
session.save(user);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}finally{
//Session关闭,那么user由持久对象变成脱管对象
HibernateUtils.closeSession(session);
}
Session session1 = HibernateUtils.getSession();
Transaction tx1 = session1.beginTransaction();
try {
user.setUname("亮亮");
//Session1接纳了user,立即把user变成持久对象
session1.update(user);
tx1.commit();
} catch (Exception e) {
e.printStackTrace();
tx1.rollback();
}finally{
HibernateUtils.closeResource(session1);
}
}
@Test
public void test5(){
Session session = HibernateUtils.getSession();
Transaction tx = session.beginTransaction();
try {
//通过get方法查询的对象既在Session管理中,在数据库中也有记录所以user是持久对象
User user = (User) session.get(User.class, 5);
System.out.println(user);
user.setUname("liangliang");
//发出update语句,证明是持久对象
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
@Test
public void test6(){
Session session = HibernateUtils.getSession();
Transaction tx = session.beginTransaction();
try {
//通过get方法查询的对象既在Session管理中,在数据库中也有记录所以user是持久对象
User user = (User) session.load(User.class, 5);
System.out.println(user);
user.setUname("任亮");
//发出update语句,证明是持久对象
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
通过delete把数据库中的数据删除,而且清掉Session中的对象,那么这个对象就变成了瞬时对象
@Test
public void test7(){
Session session = HibernateUtils.getSession();
Transaction tx = session.beginTransaction();
try {
//通过get方法查询的对象既在Session管理中,在数据库中也有记录所以user是持久对象
User user = (User) session.get(User.class, 5);
System.out.println(user);
//session的删除会把数据库中的记录删掉,同时清掉Session的user对象
session.delete(user);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
Read uncommitted | Y | Y | Y |
Read commited | N | Y | Y |
Repeatable read | N | N | Y |
Serializable | N | N | N |
@Test
public void test1(){
Session session = HibernateUtils.getSession();
Transaction tx = session.beginTransaction();
try {
User user = new User();
user.setUname("任亮");
user.setGender(1);
user.setBirthday(new Date());
//因为是uuid方式生成的主键,由Session给生成,把user对象存储在Session的临时存储区
session.save(user);
//发出sql语句,清理临时存储区,把dirty变成false
session.flush();
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtils.closeResource(session);
}
}
@Test
public void test3(){
Session session = HibernateUtils.getSession();
Transaction tx = session.beginTransaction();
try {
User user = new User();
user.setUname("任亮");
user.setGender(1);
user.setBirthday(new Date());
//因为是使用native方式生成主键,所以save的时候要发出sql来产生主键,持久区有数据,dirty是true
session.save(user);
//把dirty变成false
session.flush();
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtils.closeResource(session);
}
}
@Test
public void test4(){
Session session = HibernateUtils.getSession();
Transaction tx = session.beginTransaction();
try {
User user = new User();
user.setUname("任亮");
user.setGender(1);
user.setBirthday(new Date());
//因为是使用native方式生成主键,所以save的时候要发出sql来产生主键,持久区有数据,dirty是true
session.save(user);
//把user逐出Session
session.evict(user);
//Session中没有数据flush没有意义
session.flush();
//但是commit依然会把数据提交到数据库,因为sql已经发出了
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtils.closeResource(session);
}
}
@Test
public void test5(){
Session session = HibernateUtils.getSession();
Transaction tx = session.beginTransaction();
try {
for(int i = 0; i < 100009; i++){
User user = new User();
user.setUname("任亮");
user.setGender(1);
user.setBirthday(new Date());
session.save(user);
if(i%100 == 0){
session.flush();
}
}
session.flush();
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtils.closeResource(session);
}
}
多的一端
<hibernate-mapping package="com.rl.hiber.model">
<class name="Emp" table="t_emp">
<id name="empNo" column="emp_no">
<generator class="native">generator>
id>
<property name="ename">property>
<property name="birthday">property>
<property name="gender">property>
<property name="address">property>
<many-to-one name="team" column="t_id">many-to-one>
class>
一的一端
<hibernate-mapping package="com.rl.hiber.model">
<class name="Team" table="t_team">
<id name="tId" column="t_id">
<generator class="native">generator>
id>
<property name="tName" column="t_name">property>
<property name="loc">property>
class>
hibernate-mapping>
Hibernate的映射文件创建后要注册到我们的hibernate.cfg.xml中,然后导出数据库即可
@Test
public void testAdd(){
Session session = HibernateUtils.getSession();
Transaction tx = session.beginTransaction();
try {
//创建一支球队
Team t = new Team();
t.settName("公牛");
t.setLoc("芝加哥");
//保存球队
session.save(t);
//创建员工
Emp emp = new Emp();
emp.setEname("乔丹");
emp.setGender(1);
emp.setBirthday(new Date());
emp.setAddress("芝加哥");
Emp emp1 = new Emp();
emp1.setEname("菲尔");
emp1.setGender(1);
emp1.setBirthday(new Date());
emp1.setAddress("芝加哥");
//设置员工和球队的关系
emp.setTeam(t);
emp1.setTeam(t);
//保存员工
session.save(emp);
session.save(emp1);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtils.closeResource(session);
}
}
注意:在保存多的一端的时候一定要先保存一的一端,如果一的一端是瞬时对象就会报错
正确的输出
Hibernate: insert into t_team (t_name, loc) values (?, ?)
Hibernate: insert into t_emp (ename, birthday, gender, address, t_id) values (?, ?, ?, ?, ?)
Hibernate: insert into t_emp (ename, birthday, gender, address, t_id) values (?, ?, ?, ?, ?)
保存多对一的关系的时候也可以使用级联的方式
<many-to-one name="team" column="t_id" cascade="save-update">many-to-one>
使用级联的保存就不需要单独保存一的一端了
使用get和load来查询
@Test
public void testQuery(){
Session session = HibernateUtils.getSession();
try {
//调用get方法来查询指定要查询的类和id
Emp emp = (Emp) session.get(Emp.class, 5);
System.out.println(emp);
System.out.println(emp.getTeam());
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
@Test
public void testQuery1(){
Session session = HibernateUtils.getSession();
try {
Emp emp = (Emp) session.load(Emp.class, 5);
System.out.println(emp);
System.out.println(emp.getTeam());
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
例如员工和身份证的关系如下,注意这里是站在其中一个一的一端来操作的
这里主要是身份证的模型类,员工的之前也已经创建过了
这里主要是身份证的映射文件,员工的之前也已经创建过了
一的一端
<hibernate-mapping package="com.rl.hiber.model">
<class name="IDCard" table="t_id_card">
<id name="cardId" column="emp_no">
<generator class="foreign">
<param name="property">empparam>
generator>
id>
<property name="cardNo" column="card_no">property>
<one-to-one name="emp" constrained="true">one-to-one>
class>
hibernate-mapping>
public void testAdd(){
Session session = HibernateUtils.getSession();
Transaction tx = session.beginTransaction();
try {
//创建员工
Emp emp = new Emp();
emp.setEname("任亮");
emp.setAddress("吉林");
emp.setGender(1);
emp.setBirthday(new Date());
//创建身份证
IDCard ic = new IDCard();
ic.setCardNo("1234567890");
//指定一对一的关系
ic.setEmp(emp);
//保存ic的时候自动的保存了emp,因为ic的主键是emp的主键,
//如果emp不保存主键就不会返回,所以在ic保存之前必须先保存emp
session.save(ic);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtils.closeResource(session);
}
}
@Test
public void testQuery(){
Session session = HibernateUtils.getSession();
try {
IDCard card = (IDCard) session.get(IDCard.class, 1);
System.out.println(card);
System.out.println(card.getEmp());
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: select idcard0_.emp_no as emp_no1_1_0_, idcard0_.card_no as card_no2_1_0_ from t_id_card idcard0_ where idcard0_.emp_no=?
IDCard [cardId=1, cardNo=1234567890]
Hibernate: select emp0_.emp_no as emp_no1_0_0_, emp0_.ename as ename2_0_0_, emp0_.birthday as birthday3_0_0_, emp0_.gender as gender4_0_0_, emp0_.address as address5_0_0_ from t_emp emp0_ where emp0_.emp_no=?
Emp [empNo=1, ename=任亮, birthday=2015-09-15 22:29:17.0, gender=1, address=吉林]
修改emp的模型,加入idcard这一端的属性
在emp.hbm.xml中的配置
<hibernate-mapping package="com.rl.hiber.model">
<class name="Emp" table="t_emp">
<id name="empNo" column="emp_no">
<generator class="native">generator>
id>
<property name="ename">property>
<property name="birthday">property>
<property name="gender">property>
<property name="address">property>
<one-to-one name="card">one-to-one>
class>
hibernate-mapping>
@Test
public void testAdd(){
Session session = HibernateUtils.getSession();
Transaction tx = session.beginTransaction();
try {
//创建员工
Emp emp = new Emp();
emp.setEname("任亮");
emp.setAddress("吉林");
emp.setGender(1);
emp.setBirthday(new Date());
//创建身份证
IDCard ic = new IDCard();
ic.setCardNo("1234567890");
//设置员工和身份证的关系,由于是双向映射需要指定双向的关系
emp.setCard(ic);
ic.setEmp(emp);
//先保存emp
session.save(emp);
//保存ic
session.save(ic);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtils.closeResource(session);
}
}
使用级联方式
@Test
public void testAdd1(){
Session session = HibernateUtils.getSession();
Transaction tx = session.beginTransaction();
try {
//创建员工
Emp emp = new Emp();
emp.setEname("任亮");
emp.setAddress("吉林");
emp.setGender(1);
emp.setBirthday(new Date());
//创建身份证
IDCard ic = new IDCard();
ic.setCardNo("1234567890");
//设置员工和身份证的关系,由于是双向映射需要指定双向的关系
emp.setCard(ic);
ic.setEmp(emp);
//先保存emp
session.save(emp);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtils.closeResource(session);
}
}
@Test
public void testQuery(){
Session session = HibernateUtils.getSession();
try {
Emp emp = (Emp) session.get(Emp.class, 3);
System.out.println(emp);
System.out.println(emp.getCard());
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
从箭头指向的方向查询会使用连接查询
Hibernate: select emp0_.emp_no as emp_no1_0_0_, emp0_.ename as ename2_0_0_, emp0_.birthday as birthday3_0_0_, emp0_.gender as gender4_0_0_, emp0_.address as address5_0_0_, idcard1_.emp_no as emp_no1_1_1_, idcard1_.card_no as card_no2_1_1_ from t_emp emp0_ left outer join t_id_card idcard1_ on emp0_.emp_no=idcard1_.emp_no where emp0_.emp_no=?
Emp [empNo=3, ename=任亮, birthday=2015-09-15 22:51:19.0, gender=1, address=吉林]
IDCard [cardId=3, cardNo=1234567890]
在一的一端来配置
<hibernate-mapping package="com.rl.hiber.model">
<class name="Team" table="t_team">
<id name="tId" column="t_id">
<generator class="native">generator>
id>
<property name="tName" column="t_name">property>
<property name="loc">property>
<set name="set">
<key column="t_id">key>
<one-to-many class="Emp"/>
set>
class>
hibernate-mapping>
@Test
public void testAdd(){
Session session = HibernateUtils.getSession();
Transaction tx = session.beginTransaction();
try {
//创建员工
Emp emp = new Emp();
emp.setEname("乔丹");
emp.setAddress("芝加哥");
emp.setBirthday(new Date());
emp.setGender(1);
//保存员工
session.save(emp);
Emp emp1 = new Emp();
emp1.setEname("菲尔");
emp1.setAddress("芝加哥");
emp1.setBirthday(new Date());
emp1.setGender(1);
session.save(emp1);
//创建球队
Team team = new Team();
team.settName("公牛队");
team.setLoc("芝加哥");
//把两个员工加入到集合中
Set<Emp> set = new HashSet<Emp>();
set.add(emp);
set.add(emp1);
//指定球队和员工一对多的关系
team.setSet(set);
//保存球队
session.save(team);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: insert into t_emp (ename, birthday, gender, address) values (?, ?, ?, ?)
Hibernate: insert into t_emp (ename, birthday, gender, address) values (?, ?, ?, ?)
Hibernate: insert into t_team (t_name, loc) values (?, ?)
Hibernate: update t_emp set t_id=? where emp_no=?
Hibernate: update t_emp set t_id=? where emp_no=?
从输出上可以看出来在保存员工时先插入员工的基本字段,外键t_id是空的,再插入球队最后根据生成的球队的t_id来修改两个员工的球队外键t_id。
缺点是如果员工表中外键为非空插入员工时就会报错。
@Test
public void testQuery(){
Session session = HibernateUtils.getSession();
try{
Team team = (Team) session.get(Team.class, 3);
System.out.println(team);
Set<Emp> set = team.getSet();
for(Emp emp : set){
System.out.println(emp);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: select team0_.t_id as t_id1_1_0_, team0_.t_name as t_name2_1_0_, team0_.loc as loc3_1_0_ from t_team team0_ where team0_.t_id=?
Team [tId=3, tName=小牛队, loc=达拉斯]
Hibernate: select set0_.t_id as t_id6_1_0_, set0_.emp_no as emp_no1_0_0_, set0_.emp_no as emp_no1_0_1_, set0_.ename as ename2_0_1_, set0_.birthday as birthday3_0_1_, set0_.gender as gender4_0_1_, set0_.address as address5_0_1_ from t_emp set0_ where set0_.t_id=?
Emp [empNo=4, ename=诺维斯基, birthday=2015-09-16 10:29:00.0, gender=1, address=达拉斯]
Emp [empNo=3, ename=库班, birthday=2015-09-16 10:29:00.0, gender=1, address=达拉斯]
一对多是有缺陷的,保存的时候如果多的一端的外键是非空,一对多的保存就不成立
修改多的一端的配置
<hibernate-mapping package="com.rl.hiber.model">
<class name="Emp" table="t_emp">
<id name="empNo" column="emp_no">
<generator class="native">generator>
id>
<property name="ename">property>
<property name="birthday">property>
<property name="gender">property>
<property name="address">property>
<many-to-one name="team" column="t_id">many-to-one>
class>
保存一对多的,要把操作给多的一端去操作
@Test
public void testAdd(){
Session session = HibernateUtils.getSession();
Transaction tx = session.beginTransaction();
try {
//创建球队
Team team = new Team();
team.settName("公牛队");
team.setLoc("芝加哥");
//保存球队
session.save(team);
//创建员工
Emp emp = new Emp();
emp.setEname("乔丹");
emp.setAddress("芝加哥");
emp.setBirthday(new Date());
emp.setGender(1);
//指定员工和球队的关系
emp.setTeam(team);
//保存员工
session.save(emp);
Emp emp1 = new Emp();
emp1.setEname("菲尔");
emp1.setAddress("芝加哥");
emp1.setBirthday(new Date());
emp1.setGender(1);
emp1.setTeam(team);
session.save(emp1);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: insert into t_team (t_name, loc) values (?, ?)
Hibernate: insert into t_emp (ename, birthday, gender, address, t_id) values (?, ?, ?, ?, ?)
Hibernate: insert into t_emp (ename, birthday, gender, address, t_id) values (?, ?, ?, ?, ?)
如果有需求必须要在一的一端来进行保存,我们设置控制反转,我们可以在一的一端操作,然后实际是在多的一端保存
@Test
public void testAdd1(){
Session session = HibernateUtils.getSession();
Transaction tx = session.beginTransaction();
try {
//创建球队
Team team = new Team();
team.settName("公牛队");
team.setLoc("芝加哥");
//创建员工
Emp emp = new Emp();
emp.setEname("乔丹");
emp.setAddress("芝加哥");
emp.setBirthday(new Date());
emp.setGender(1);
//指定员工和球队的关系
emp.setTeam(team);
Emp emp1 = new Emp();
emp1.setEname("菲尔");
emp1.setAddress("芝加哥");
emp1.setBirthday(new Date());
emp1.setGender(1);
emp1.setTeam(team);
Set<Emp> set = new HashSet<Emp>();
set.add(emp1);
set.add(emp);
team.setSet(set);
//保存球队
session.save(team);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: insert into t_team (t_name, loc) values (?, ?)
Hibernate: insert into t_emp (ename, birthday, gender, address, t_id) values (?, ?, ?, ?, ?)
Hibernate: insert into t_emp (ename, birthday, gender, address, t_id) values (?, ?, ?, ?, ?)
员工和角色是多对多的关系,一个员工可以分配多个角色,一个角色可以分配给多个员工
<hibernate-mapping package="com.rl.hiber.model">
<class name="Emp" table="t_emp">
<id name="empNo" column="emp_no">
<generator class="native">generator>
id>
<property name="ename">property>
<property name="birthday">property>
<property name="gender">property>
<property name="address">property>
<set name="roles" table="emp_role">
<key column="emp_no">key>
<many-to-many class="Role" column="role_id">many-to-many>
set>
class>
hibernate-mapping>
@Test
public void testAdd(){
Session session = HibernateUtils.getSession();
Transaction tx = session.beginTransaction();
try {
//创建员工
Emp emp = new Emp();
emp.setEname("任亮");
emp.setGender(1);
emp.setAddress("长春");
emp.setBirthday(new Date());
//创建角色
Role role = new Role();
role.setRoleName("老师");
role.setRoleDesc("讲课");
//保存角色
session.save(role);
Role role1 = new Role();
role1.setRoleName("总监");
role1.setRoleDesc("管理");
//保存角色
session.save(role1);
//指定当前员工和角色的关系
Set<Role> set = new HashSet<Role>();
set.add(role);
set.add(role1);
emp.setRoles(set);
//保存员工
session.save(emp);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: insert into t_role (role_name, role_desc) values (?, ?)
Hibernate: insert into t_role (role_name, role_desc) values (?, ?)
Hibernate: insert into t_emp (ename, birthday, gender, address) values (?, ?, ?, ?)
Hibernate: insert into emp_role (emp_no, role_id) values (?, ?)
Hibernate: insert into emp_role (emp_no, role_id) values (?, ?)
@Test
public void queryTest(){
Session session = HibernateUtils.getSession();
try{
Emp emp = (Emp) session.get(Emp.class, 1);
System.out.println(emp);
for(Role role : emp.getRoles()){
System.out.println(role);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
<hibernate-mapping package="com.rl.hiber.model">
<class name="Role" table="t_role">
<id name="roleId" column="role_id">
<generator class="native">generator>
id>
<property name="roleName" column="role_name">property>
<property name="roleDesc" column="role_desc">property>
<set name="emps" table="emp_role" cascade="save-update">
<key column="role_id">key>
<many-to-many class="Emp" column="emp_no">many-to-many>
set>
class>
hibernate-mapping>
我们通过get和load来查询,get默认不使用延迟加载,load使用延迟加载,延迟加载必须在同一个Session范围内。
Get方法
@Test
public void testQueryWGet(){
Session session = HibernateUtils.getSession();
try {
//get方法不使用延迟加载,发出sql的
User user = (User) session.get(User.class, "297e045d4fd4ddbc014fd4ddbe100000");
System.out.println(user.getUname());
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
Load方法
@Test
public void testQueryWLoad(){
Session session = HibernateUtils.getSession();
try {
//load方法默认使用延迟加载,不发出sql的
User user = (User) session.load(User.class, "297e045d4fd4ddbc014fd4ddbe100000");
//使用到对象的成员时来发出sql
System.out.println(user.getUname());
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
延迟加载必须在同一个Session内
/**
* 类上的延迟加载要在同一个Session之内
*/
@Test
public void testQueryWLoad1(){
Session session = HibernateUtils.getSession();
User user = null;
try {
//load方法默认使用延迟加载,不发出sql的
user = (User) session.load(User.class, "297e045d4fd4ddbc014fd4ddbe100000");
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
//Session关闭了就不会有延迟加载,不发sql
System.out.println(user.getUname());
}
集合的延迟加载是在一对多和多对多,默认情况集合是有延迟加载的
@Test
public void testQuery(){
Session session = HibernateUtils.getSession();
try {
Team team = (Team) session.load(Team.class, 1);
//发出查询team的sql
System.out.println(team);
Set<Emp> emps = team.getSet();
//发出根据t_id查询员工的sql
System.out.println(emps);
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
输出
Hibernate: select team0_.t_id as t_id1_1_0_, team0_.t_name as t_name2_1_0_, team0_.loc as loc3_1_0_ from t_team team0_ where team0_.t_id=?
Team [tId=1, tName=公牛队, loc=芝加哥]
Hibernate: select set0_.t_id as t_id6_1_0_, set0_.emp_no as emp_no1_0_0_, set0_.emp_no as emp_no1_0_1_, set0_.ename as ename2_0_1_, set0_.birthday as birthday3_0_1_, set0_.gender as gender4_0_1_, set0_.address as address5_0_1_, set0_.t_id as t_id6_0_1_ from t_emp set0_ where set0_.t_id=?
[Emp [empNo=1, ename=乔丹, birthday=2015-09-16 15:01:36.0, gender=1, address=芝加哥], Emp [empNo=2, ename=菲尔, birthday=2015-09-16 15:01:36.0, gender=1, address=芝加哥]]
Hibernate: select team0_.t_id as t_id1_1_0_, team0_.t_name as t_name2_1_0_, team0_.loc as loc3_1_0_ from t_team team0_ where team0_.t_id=?
Hibernate: select set0_.t_id as t_id6_1_0_, set0_.emp_no as emp_no1_0_0_, set0_.emp_no as emp_no1_0_1_, set0_.ename as ename2_0_1_, set0_.birthday as birthday3_0_1_, set0_.gender as gender4_0_1_, set0_.address as address5_0_1_, set0_.t_id as t_id6_0_1_ from t_emp set0_ where set0_.t_id=?
Team [tId=1, tName=公牛队, loc=芝加哥]
[Emp [empNo=2, ename=菲尔, birthday=2015-09-16 15:01:36.0, gender=1, address=芝加哥], Emp [empNo=1, ename=乔丹, birthday=2015-09-16 15:01:36.0, gender=1, address=芝加哥]]
当lazy=true的时候,如果查询集合的数量时,效率低下,我们需要把lazy=extra,效率比较高
/**
* lazy=extra
*/
@Test
public void testQuery2(){
Session session = HibernateUtils.getSession();
try {
Team team = (Team) session.load(Team.class, 1);
//发出查询team的sql
System.out.println(team);
Set<Emp> emps = team.getSet();
//发出一条智能高效的sql
System.out.println(emps.size());
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: select team0_.t_id as t_id1_1_0_, team0_.t_name as t_name2_1_0_, team0_.loc as loc3_1_0_ from t_team team0_ where team0_.t_id=?
Team [tId=1, tName=公牛队, loc=芝加哥]
Hibernate: select count(emp_no) from t_emp where t_id =?
2
注意:集合的延迟加载效果不受类上的延迟加载影响。
针对多对一和一对一的延迟加载,默认情况lazy=proxy使用延迟加载
/**
* 默认情况many-to-one=proxy
*/
@Test
public void testQuery(){
Session session = HibernateUtils.getSession();
try {
//不发sql
Emp emp = (Emp) session.load(Emp.class, 1);
//发出一条根据emp_no查询员工的sql
System.out.println(emp);
//不发
Team team = emp.getTeam();
//发出一条根据t_id查询球队的sql
System.out.println(team);
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: select emp0_.emp_no as emp_no1_0_0_, emp0_.ename as ename2_0_0_, emp0_.birthday as birthday3_0_0_, emp0_.gender as gender4_0_0_, emp0_.address as address5_0_0_, emp0_.t_id as t_id6_0_0_ from t_emp emp0_ where emp0_.emp_no=?
Emp [empNo=1, ename=乔丹, birthday=2015-09-16 16:05:14.0, gender=1, address=芝加哥]
Hibernate: select team0_.t_id as t_id1_1_0_, team0_.t_name as t_name2_1_0_, team0_.loc as loc3_1_0_ from t_team team0_ where team0_.t_id=?
Team [tId=1, tName=公牛队, loc=芝加哥]
Lazy=false
/**
* lazy=false
*/
@Test
public void testQuery1(){
Session session = HibernateUtils.getSession();
try {
//不发sql
Emp emp = (Emp) session.load(Emp.class, 1);
//发出一条根据emp_no查询员工的sql,发出一条根据t_id查询球队的sql
System.out.println(emp);
//不发
Team team = emp.getTeam();
//不发
System.out.println(team);
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: select emp0_.emp_no as emp_no1_0_0_, emp0_.ename as ename2_0_0_, emp0_.birthday as birthday3_0_0_, emp0_.gender as gender4_0_0_, emp0_.address as address5_0_0_, emp0_.t_id as t_id6_0_0_ from t_emp emp0_ where emp0_.emp_no=?
Hibernate: select team0_.t_id as t_id1_1_0_, team0_.t_name as t_name2_1_0_, team0_.loc as loc3_1_0_ from t_team team0_ where team0_.t_id=?
Emp [empNo=1, ename=乔丹, birthday=2015-09-16 16:05:14.0, gender=1, address=芝加哥]
Team [tId=1, tName=公牛队, loc=芝加哥]
如果Team类的延迟加载被禁用,many-to-one lazy=proxy
/**
* 如果Team类的延迟加载被禁用,many-to-one lazy=proxy
*/
@Test
public void testQuery2(){
Session session = HibernateUtils.getSession();
try {
//不发sql
Emp emp = (Emp) session.load(Emp.class, 1);
//发出一条根据emp_no查询员工和球队的连接查询的sql
System.out.println(emp);
//不发
Team team = emp.getTeam();
//不发
System.out.println(team.gettName());
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: select emp0_.emp_no as emp_no1_0_0_, emp0_.ename as ename2_0_0_, emp0_.birthday as birthday3_0_0_, emp0_.gender as gender4_0_0_, emp0_.address as address5_0_0_, emp0_.t_id as t_id6_0_0_, team1_.t_id as t_id1_1_1_, team1_.t_name as t_name2_1_1_, team1_.loc as loc3_1_1_ from t_emp emp0_ left outer join t_team team1_ on emp0_.t_id=team1_.t_id where emp0_.emp_no=?
Emp [empNo=1, ename=乔丹, birthday=2015-09-16 16:05:14.0, gender=1, address=芝加哥]
公牛队
HQL(Hibernate Query Language),hibernate的专属语言,可以跨数据库,根据不同数据库方言翻译成不同sql,跟SQL很相似。
查询所有的数据的写法
String hql = "from User";
String hql = "select u from User u";//hql中没有*的写法
@Test
public void testQuery1(){
Session session = HibernateUtils.getSession();
try {
//查询所有的user类的对象
String hql = "from User";
//根据hql语句创建查询对象
Query query = session.createQuery(hql);
//查询列表
List<User> userList = query.list();
for(User user: userList){
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: select user0_.user_id as user_id1_0_, user0_.uname as uname2_0_, user0_.gender as gender3_0_, user0_.birthday as birthday4_0_ from t_user user0_
User [userId=1, uname=任亮0, gender=1, birthday=2015-09-16 22:19:02.0]
User [userId=2, uname=任亮1, gender=2, birthday=2015-09-16 22:19:02.0]
User [userId=3, uname=任亮2, gender=1, birthday=2015-09-16 22:19:02.0]
User [userId=4, uname=任亮3, gender=2, birthday=2015-09-16 22:19:02.0]
User [userId=5, uname=任亮4, gender=1, birthday=2015-09-16 22:19:02.0]
User [userId=6, uname=任亮5, gender=2, birthday=2015-09-16 22:19:02.0]
User [userId=7, uname=任亮6, gender=1, birthday=2015-09-16 22:19:02.0]
User [userId=8, uname=任亮7, gender=2, birthday=2015-09-16 22:19:02.0]
User [userId=9, uname=任亮8, gender=1, birthday=2015-09-16 22:19:02.0]
User [userId=10, uname=任亮9, gender=2, birthday=2015-09-16 22:19:02.0]
对象的单个属性查询
/**
* 查询对象的属性
*/
@Test
public void testQuery2(){
Session session = HibernateUtils.getSession();
try {
//查询所有的user类的对象
//String hql = "from User";
String hql = "select u.uname from User u";//hql中没有*的写法
//根据hql语句创建查询对象
Query query = session.createQuery(hql);
//查询列表
List<String> nameList = query.list();
for(String name: nameList){
System.out.println(name);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: select user0_.uname as col_0_0_ from t_user user0_
任亮0
任亮1
任亮2
任亮3
任亮4
任亮5
任亮6
任亮7
任亮8
任亮9
多个属性的查询
/**
* 查询对象的多个属性
*/
@Test
public void testQuery3(){
Session session = HibernateUtils.getSession();
try {
//查询所有的user类的对象
//String hql = "from User";
String hql = "select u.uname, u.gender from User u";//hql中没有*的写法
//根据hql语句创建查询对象
Query query = session.createQuery(hql);
//查询列表,多个属性的查询要使用Object[]来做接收
List<Object[]> objArrList = query.list();
for(Object[] objArr: objArrList){
System.out.println("姓名:"+objArr[0]+" 性别:"+objArr[1]);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: select user0_.uname as col_0_0_, user0_.gender as col_1_0_ from t_user user0_
姓名:任亮0 性别:1
姓名:任亮1 性别:2
姓名:任亮2 性别:1
姓名:任亮3 性别:2
姓名:任亮4 性别:1
姓名:任亮5 性别:2
姓名:任亮6 性别:1
姓名:任亮7 性别:2
姓名:任亮8 性别:1
姓名:任亮9 性别:2
setFirstResult(m)
etMaxResults(n)
m表示起始的索引
n表示每页的记录数
@Test
public void testQuery5(){
Session session = HibernateUtils.getSession();
try {
//查询所有的user类的对象
//String hql = "from User";
String hql = "select u from User u";//hql中没有*的写法
//根据hql语句创建查询对象
Query query = session.createQuery(hql);
//从前台传递过来的是页码PageNo, startNum = (pageNo - 1)*pageSize
//查询列表
List<User> userList = query.setFirstResult(5)
.setMaxResults(5)
.list();
for(User user: userList){
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: select user0_.user_id as user_id1_0_, user0_.uname as uname2_0_, user0_.gender as gender3_0_, user0_.birthday as birthday4_0_ from t_user user0_ limit ?, ?
User [userId=6, uname=任亮5, gender=2, birthday=2015-09-16 22:19:02.0]
User [userId=7, uname=任亮6, gender=1, birthday=2015-09-16 22:19:02.0]
User [userId=8, uname=任亮7, gender=2, birthday=2015-09-16 22:19:02.0]
User [userId=9, uname=任亮8, gender=1, birthday=2015-09-16 22:19:02.0]
User [userId=10, uname=任亮9, gender=2, birthday=2015-09-16 22:19:02.0]
限定查询第一种方式
/**
* 限定查询
*/
@Test
public void testQuery5(){
Session session = HibernateUtils.getSession();
try {
String hql = "select u from User u where u.gender = ? and u.uname = ?";//hql中没有*的写法
Query query = session.createQuery(hql);
//设置第一个参数的值,和JDBC不同,预编译的索引从0开始
query.setParameter(0, 2);
query.setParameter(1, "任亮5");
List<User> userList = query.list();
for(User user : userList){
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: select user0_.user_id as user_id1_0_, user0_.uname as uname2_0_, user0_.gender as gender3_0_, user0_.birthday as birthday4_0_ from t_user user0_ where user0_.gender=? and user0_.uname=?
User [userId=6, uname=任亮5, gender=2, birthday=2015-09-16 22:19:02.0]
限定查询第二种方式
/**
* 限定查询
*/
@Test
public void testQuery6(){
Session session = HibernateUtils.getSession();
try {
//传参的语法 :[自定义名称]
String hql = "select u from User u where u.gender = :gender and u.uname = :uname";//hql中没有*的写法
Query query = session.createQuery(hql);
//给自定义的参数赋值
query.setParameter("gender", 1);
query.setParameter("uname", "任亮8");
List<User> userList = query.list();
for(User user : userList){
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
/**
* 统计查询
*/
@Test
public void testQuery5(){
Session session = HibernateUtils.getSession();
try {
//查询记录数
//String hql = "select count(u.userId) from User u";
//查询最大值
//String hql = "select max(u.userId) from User u";
//查询最小值
//String hql = "select min(u.userId) from User u";
//查询平均值
//String hql = "select avg(u.userId) from User u";
//统计求和
String hql = "select sum(u.userId) from User u";
Query query = session.createQuery(hql);
//查询唯一的结果
Object obj = query.uniqueResult();
System.out.println(obj);
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
@Test
public void testQuery6(){
Session session = HibernateUtils.getSession();
try {
//统计求和
String hql = "select avg(u.salary), u.gender from User u group by u.gender having avg(u.salary) > 1400";
Query query = session.createQuery(hql);
//查询唯一的结果
List<Object[]> objArrList = query.list();
for(Object[] objArr : objArrList){
System.out.println("平均工资:" + objArr[0]+ " 性别:"+objArr[1]);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
/**
* 投影查询
*/
@Test
public void testQuery7(){
Session session = HibernateUtils.getSession();
try {
//我们可以创建一个业务Bean,在Bean提供有参数的构造器来接收sql返回的值,创建出对象语法 在select后面new com.rl.hiber.model.EmpBean(max(u.salary), u.gender)
String hql = "select new com.rl.hiber.model.EmpBean(max(u.salary), u.gender) from User u group by u.gender having avg(u.salary) > 1400";
Query query = session.createQuery(hql);
//查询唯一的结果
List<EmpBean> objArrList = query.list();
for(EmpBean objArr : objArrList){
System.out.println(objArr);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
/**
* 按着工资排序
*/
@Test
public void testQuery1(){
Session session = HibernateUtils.getSession();
try {
//查询所有的user类的对象
//String hql = "from User";
String hql = "select u from User u order by u.salary desc";//hql中没有*的写法
//根据hql语句创建查询对象
Query query = session.createQuery(hql);
//查询列表
List<User> userList = query.list();
for(User user: userList){
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
/**
* 模糊查询
*/
@Test
public void testQuery2(){
Session session = HibernateUtils.getSession();
try {
//String hql = "select u from User u where u.uname like '%亮%'";//hql中没有*的写法
//模糊查询和sql中的语法一致
String hql = "select u from User u where u.uname like '%亮_'";//hql中没有*的写法
//根据hql语句创建查询对象
Query query = session.createQuery(hql);
//查询列表
List<User> userList = query.list();
for(User user: userList){
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
<hibernate-mapping package="com.rl.hiber.model">
<class name="User" table="t_user">
<id name="userId" column="user_id">
<generator class="native">generator>
id>
<property name="uname">property>
<property name="salary">property>
<property name="gender">property>
<property name="birthday">property>
class>
<query name="getUserAll">
:salary
]]>
query>
hibernate-mapping>
查询:
@Test
public void testQuery2(){
Session session = HibernateUtils.getSession();
try {
//从映射文件中获得hql语句创建query对象
Query query = session.getNamedQuery("getUserAll");
query.setParameter("salary", 1500);
//查询列表
List<User> userList = query.list();
for(User user: userList){
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: select user0_.user_id as user_id1_0_, user0_.uname as uname2_0_, user0_.salary as salary3_0_, user0_.gender as gender4_0_, user0_.birthday as birthday5_0_ from t_user user0_ where user0_.salary>?
User [userId=7, uname=任亮6, gender=1, salary=1600, birthday=2015-09-16 23:06:25.0]
User [userId=8, uname=任亮7, gender=2, salary=1700, birthday=2015-09-16 23:06:25.0]
User [userId=9, uname=任亮8, gender=1, salary=1800, birthday=2015-09-16 23:06:25.0]
User [userId=10, uname=任亮9, gender=2, salary=1900, birthday=2015-09-16 23:06:25.0]
QBC(Query By Criteria)是hibernate提供的一套查询API,跨数据库。
查询User的对象
/**
* QBC的对象全量查询
*/
@Test
public void testQuery1(){
Session session = HibernateUtils.getSession();
try {
//创建qbc的查询接口的实现类
Criteria c = session.createCriteria(User.class);
//查询User类对象的列表
List<User> userList = c.list();
for(User user : userList){
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
单个属性的查询
/**
* 查询单个属性
*/
@Test
public void testQuery2(){
Session session = HibernateUtils.getSession();
try {
//创建qbc的查询接口的实现类
Criteria c = session.createCriteria(User.class);
//获得具体要查询的属性
PropertyProjection pp = Projections.property("uname");
//设置具体要查询的列
c.setProjection(pp);
//查询User类对象的列表
List<String> unames = c.list();
for(String name : unames){
System.out.println(name);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: select this_.uname as y0_ from t_user this_
User对象多个属性的查询
@Test
public void testQuery3(){
Session session = HibernateUtils.getSession();
try {
//创建qbc的查询接口的实现类
Criteria c = session.createCriteria(User.class);
//创建要查询的列的集合
ProjectionList pl = Projections.projectionList();
//获得具体要查询的属性
PropertyProjection pp = Projections.property("uname");
PropertyProjection pp1 = Projections.property("gender");
//把要查询的属性加入到集合中
pl.add(pp);
pl.add(pp1);
//设置具体要查询的列
c.setProjection(pl);
//查询User类对象的列表
List<Object[]> objArrList = c.list();
for(Object[] objArr : objArrList){
System.out.println("姓名:"+objArr[0]+ " 性别:"+objArr[1]);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: select this_.uname as y0_, this_.gender as y1_ from t_user this_
姓名:任亮0 性别:1
姓名:任亮1 性别:2
姓名:任亮2 性别:1
/**
* QBC统计查询
*/
@Test
public void testQuery1(){
Session session = HibernateUtils.getSession();
try {
//创建qbc的查询接口的实现类
Criteria c = session.createCriteria(User.class);
//设置要查询的项
c.setProjection(Projections.rowCount());
Object obj = c.uniqueResult();
System.out.println("总记录数:"+obj);
//设置要查询薪水的最大值
c.setProjection(Projections.max("salary"));
Object obj1 = c.uniqueResult();
System.out.println("最高薪水:"+obj1);
//设置要查询薪水的最小值
c.setProjection(Projections.min("salary"));
Object obj2 = c.uniqueResult();
System.out.println("最低薪水:"+obj2);
//设置要查询薪水的平均值
c.setProjection(Projections.avg("salary"));
Object obj3 = c.uniqueResult();
System.out.println("平均薪水:"+obj3);
//设置要查询薪水的平均值
c.setProjection(Projections.sum("salary"));
Object obj4 = c.uniqueResult();
System.out.println("员工薪水总和:"+obj4);
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: select count(*) as y0_ from t_user this_
总记录数:10
Hibernate: select max(this_.salary) as y0_ from t_user this_
最高薪水:1900
Hibernate: select min(this_.salary) as y0_ from t_user this_
最低薪水:1000
Hibernate: select avg(this_.salary) as y0_ from t_user this_
平均薪水:1450.0
Hibernate: select sum(this_.salary) as y0_ from t_user this_
员工薪水总和:14500
/**
* 分组统计查询
*/
@Test
public void testQuery2(){
Session session = HibernateUtils.getSession();
try {
//创建qbc的查询接口的实现类
Criteria c = session.createCriteria(User.class);
//创建查询项的集合
ProjectionList pl = Projections.projectionList();
//创建查询项
PropertyProjection pp = Projections.property("gender");
//创建统计项
AggregateProjection ap = Projections.max("salary");
//设置按着哪一项分组
PropertyProjection pp1 = Projections.groupProperty("gender");
//把要查询的项加入到集合
pl.add(pp);
pl.add(ap);
pl.add(pp1);
//把查询集合设置给qbc接口
c.setProjection(pl);
List<Object[]> objArrList = c.list();
for(Object[] objArr : objArrList){
System.out.println("性别:"+objArr[0]+ " 最高的工资是:"+objArr[1]);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: select this_.gender as y0_, max(this_.salary) as y1_, this_.gender as y2_ from t_user this_ group by this_.gender
性别:1 最高的工资是:1800
性别:2 最高的工资是:1900
/**
* QBC的排序
*/
@Test
public void testQuery1(){
Session session = HibernateUtils.getSession();
try {
//创建qbc的查询接口的实现类
Criteria c = session.createCriteria(User.class);
//设置排序字段
c.addOrder(Order.desc("salary"));
//查询User类对象的列表
List<User> userList = c.list();
for(User user : userList){
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
/**
* QBC分页查询
*/
@Test
public void testQuery2(){
Session session = HibernateUtils.getSession();
try {
//创建qbc的查询接口的实现类
Criteria c = session.createCriteria(User.class);
//设置排序字段
c.addOrder(Order.desc("salary"));
//设置开始行号
c.setFirstResult(5);
//设置每页记录数
c.setMaxResults(5);
//查询User类对象的列表
List<User> userList = c.list();
for(User user : userList){
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: select this_.user_id as user_id1_0_0_, this_.uname as uname2_0_0_, this_.salary as salary3_0_0_, this_.gender as gender4_0_0_, this_.birthday as birthday5_0_0_ from t_user this_ order by this_.salary desc limit ?, ?
User [userId=5, uname=任亮4, gender=1, salary=1400, birthday=2015-09-16 23:06:25.0]
User [userId=4, uname=任亮3, gender=2, salary=1300, birthday=2015-09-16 23:06:25.0]
User [userId=3, uname=任亮2, gender=1, salary=1200, birthday=2015-09-16 23:06:25.0]
User [userId=2, uname=任亮1, gender=2, salary=1100, birthday=2015-09-16 23:06:25.0]
User [userId=1, uname=任亮0, gender=1, salary=1000, birthday=2015-09-16 23:06:25.0]
我们通过Restrictions来设置限定查询的条件
短语 | 含义 |
---|---|
Restrictions.eq | 等于= |
Restrictions.allEq | 使用Map,使用key/value进行多个等于的判断 |
Restrictions.gt | 大于> |
Restrictions.ge | 大于等于>= |
Restrictions.lt | 小于< |
Restrictions.le | 小于等于<= |
Restrictions.between | 对应sql的between子句 |
Restrictions.like | 对应sql的like子句 |
Restrictions.in | 对应sql的in子句 |
Restrictions.and | and 关系 |
Restrictions.or | or关系 |
Restrictions.sqlRestriction | Sql限定查询 |
查询工号是5
/**
* QBC限定查询
*/
@Test
public void testQuery1(){
Session session = HibernateUtils.getSession();
try {
//创建qbc的查询接口的实现类
Criteria c = session.createCriteria(User.class);
//创建查询条件
Criterion ct = Restrictions.eq("userId", 5);
//把查询条件设置给QBC的查询接口
c.add(ct);
//查询User类对象的列表
List<User> userList = c.list();
for(User user : userList){
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: select this_.user_id as user_id1_0_0_, this_.uname as uname2_0_0_, this_.salary as salary3_0_0_, this_.gender as gender4_0_0_, this_.birthday as birthday5_0_0_ from t_user this_ where this_.user_id=?
User [userId=5, uname=任亮4, gender=1, salary=1400, birthday=2015-09-16 23:06:25.0]
查询工资大于1500小于1800的员工
/**
* 工资大于1500小于1800的员工
*/
@Test
public void testQuery3(){
Session session = HibernateUtils.getSession();
try {
//创建qbc的查询接口的实现类
Criteria c = session.createCriteria(User.class);
//创建查询条件,默认查询条件使用and来做连接
Criterion ct = Restrictions.gt("salary", 1500);
Criterion ct1 = Restrictions.lt("salary", 1800);
//把查询条件设置给QBC的查询接口
c.add(ct);
c.add(ct1);
//查询User类对象的列表
List<User> userList = c.list();
for(User user : userList){
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: select this_.user_id as user_id1_0_0_, this_.uname as uname2_0_0_, this_.salary as salary3_0_0_, this_.gender as gender4_0_0_, this_.birthday as birthday5_0_0_ from t_user this_ where this_.salary>? and this_.salary<?
User [userId=7, uname=任亮6, gender=1, salary=1600, birthday=2015-09-16 23:06:25.0]
User [userId=8, uname=任亮7, gender=2, salary=1700, birthday=2015-09-16 23:06:25.0]
In的使用
@Test
public void testQuery4(){
Session session = HibernateUtils.getSession();
try {
//创建qbc的查询接口的实现类
Criteria c = session.createCriteria(User.class);
//定义要查询的in的集合(也可以是数组)
Integer[] userIds = new Integer[]{
1,2,3};
//设置查询条件
Criterion ct = Restrictions.in("userId", userIds);
c.add(ct);
//查询User类对象的列表
List<User> userList = c.list();
for(User user : userList){
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: select this_.user_id as user_id1_0_0_, this_.uname as uname2_0_0_, this_.salary as salary3_0_0_, this_.gender as gender4_0_0_, this_.birthday as birthday5_0_0_ from t_user this_ where this_.user_id in (?, ?, ?)
User [userId=1, uname=任亮0, gender=1, salary=1000, birthday=2015-09-16 23:06:25.0]
User [userId=2, uname=任亮1, gender=2, salary=1100, birthday=2015-09-16 23:06:25.0]
User [userId=3, uname=任亮2, gender=1, salary=1200, birthday=2015-09-16 23:06:25.0]
And的使用
@Test
public void testQuery5(){
Session session = HibernateUtils.getSession();
try {
//创建qbc的查询接口的实现类
Criteria c = session.createCriteria(User.class);
//and的条件的使用
Criterion ct = Restrictions.and(Restrictions.ge("salary", 1500),
Restrictions.eq("gender", 2));
c.add(ct);
//查询User类对象的列表
List<User> userList = c.list();
for(User user : userList){
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: select this_.user_id as user_id1_0_0_, this_.uname as uname2_0_0_, this_.salary as salary3_0_0_, this_.gender as gender4_0_0_, this_.birthday as birthday5_0_0_ from t_user this_ where (this_.salary>=? and this_.gender=?)
User [userId=6, uname=任亮5, gender=2, salary=1500, birthday=2015-09-16 23:06:25.0]
User [userId=8, uname=任亮7, gender=2, salary=1700, birthday=2015-09-16 23:06:25.0]
User [userId=10, uname=任亮9, gender=2, salary=1900, birthday=2015-09-16 23:06:25.0]
Or条件的使用
/**
* or
*/
@Test
public void testQuery6(){
Session session = HibernateUtils.getSession();
try {
//创建qbc的查询接口的实现类
Criteria c = session.createCriteria(User.class);
//or的条件的使用
Criterion ct = Restrictions.or(Restrictions.ge("salary", 1800),
Restrictions.eq("gender", 1));
c.add(ct);
//查询User类对象的列表
List<User> userList = c.list();
for(User user : userList){
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: select this_.user_id as user_id1_0_0_, this_.uname as uname2_0_0_, this_.salary as salary3_0_0_, this_.gender as gender4_0_0_, this_.birthday as birthday5_0_0_ from t_user this_ where (this_.salary>=? or this_.gender=?)
User [userId=1, uname=任亮0, gender=1, salary=1000, birthday=2015-09-16 23:06:25.0]
User [userId=3, uname=任亮2, gender=1, salary=1200, birthday=2015-09-16 23:06:25.0]
User [userId=5, uname=任亮4, gender=1, salary=1400, birthday=2015-09-16 23:06:25.0]
User [userId=7, uname=任亮6, gender=1, salary=1600, birthday=2015-09-16 23:06:25.0]
User [userId=9, uname=任亮8, gender=1, salary=1800, birthday=2015-09-16 23:06:25.0]
User [userId=10, uname=任亮9, gender=2, salary=1900, birthday=2015-09-16 23:06:25.0]
/**
* 模糊查询
*/
@Test
public void testQuery7(){
Session session = HibernateUtils.getSession();
try {
//创建qbc的查询接口的实现类
Criteria c = session.createCriteria(User.class);
//or的条件的使用,like的模糊查询like的第二个参数和sql语法一致,只是不需要单引号
Criterion ct = Restrictions.like("uname", "任%");
c.add(ct);
//查询User类对象的列表
List<User> userList = c.list();
for(User user : userList){
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: select this_.user_id as user_id1_0_0_, this_.uname as uname2_0_0_, this_.salary as salary3_0_0_, this_.gender as gender4_0_0_, this_.birthday as birthday5_0_0_ from t_user this_ where this_.uname like ?
User [userId=1, uname=任亮0, gender=1, salary=1000, birthday=2015-09-16 23:06:25.0]
User [userId=2, uname=任亮1, gender=2, salary=1100, birthday=2015-09-16 23:06:25.0]
User [userId=3, uname=任亮2, gender=1, salary=1200, birthday=2015-09-16 23:06:25.0]
可以使用原生sql查询
/**
* QBC的对象全量查询
*/
@Test
public void testQuery1(){
Session session = HibernateUtils.getSession();
try {
//sql定义
String sql = "select uname, gender from t_user";
//创建sql的查询接口的实现类
SQLQuery query = session.createSQLQuery(sql);
List<Object[]> objArrList = query.list();
for(Object[] objArr : objArrList){
System.out.println("姓名:"+objArr[0]+ " 性别:"+objArr[1]);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: select uname, gender from t_user
姓名:任亮0 性别:1
姓名:任亮1 性别:2
姓名:任亮2 性别:1
姓名:任亮3 性别:2
姓名:任亮4 性别:1
<hibernate-mapping package="com.rl.hiber.model">
<class name="Animal" table="t_animal">
<id name="anId" column="an_id">
<generator class="native">generator>
id>
<discriminator column="type" type="string">discriminator>
<property name="anName" column="an_name">property>
<property name="gender">property>
<subclass name="Pig" discriminator-value="p">
<property name="weight">property>
subclass>
<subclass name="Bird" discriminator-value="b">
<property name="height">property>
subclass>
class>
hibernate-mapping>
保存
@Test
public void save(){
Session session = HibernateUtils.getSession();
Transaction tx = session.beginTransaction();
try {
Pig pig = new Pig();
pig.setAnName("天蓬元帅");
pig.setGender(1);
pig.setWeight(200);
session.save(pig);
Bird b = new Bird();
b.setAnName("大鹏");
b.setGender(1);
b.setHeight(10000);
session.save(b);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: insert into t_animal (an_name, gender, weight, type) values (?, ?, ?, 'p')
Hibernate: insert into t_animal (an_name, gender, height, type) values (?, ?, ?, 'b')
子类查询
@Test
public void query(){
Session session = HibernateUtils.getSession();
try {
Pig pig = (Pig) session.load(Pig.class, 1);
System.out.println(pig.getAnName()+" "+pig.getWeight());
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: select pig0_.an_id as an_id1_0_0_, pig0_.an_name as an_name3_0_0_, pig0_.gender as gender4_0_0_, pig0_.weight as weight5_0_0_ from t_animal pig0_ where pig0_.an_id=? and pig0_.type='p'
天蓬元帅 200
查询
get支持多态查询
load的延迟加载的方式返回的是代理类,所以无法做多态查询
/**
* load的延迟加载的方式返回的是代理类,所以无法做多态查询
*/
@Test
public void query1(){
Session session = HibernateUtils.getSession();
try {
Animal animal = (Animal) session.load(Animal.class, 1);
if(animal instanceof Pig){
System.out.println("是猪");
}else{
System.out.println("不是猪");
}
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
/**
* get支持多态查询
*/
@Test
public void query2(){
Session session = HibernateUtils.getSession();
try {
Animal animal = (Animal) session.get(Animal.class, 1);
if(animal instanceof Pig){
System.out.println("是猪");
Pig pig = (Pig) animal;
System.out.println(pig.getAnName() + " "+pig.getWeight());
}else{
System.out.println("不是猪");
}
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
<hibernate-mapping package="com.rl.hiber.model">
<class name="Animal" table="t_animal">
<id name="anId" column="an_id">
<generator class="native">generator>
id>
<property name="anName" column="an_name">property>
<property name="gender">property>
<joined-subclass name="Pig" table="t_pig">
<key column="pid">key>
<property name="weight">property>
joined-subclass>
<joined-subclass name="Bird" table="t_bird">
<key column="bid">key>
<property name="height">property>
joined-subclass>
class>
hibernate-mapping>
父子表的映射因为生成的表多张,查询的时候我们需要多表连接查询,所以效率没有单表继承映射高。
配置
<hibernate-mapping package="com.rl.hiber.model">
<class name="Animal" table="t_animal" abstract="true">
<id name="anId" column="an_id">
<generator class="uuid">generator>
id>
<property name="anName" column="an_name">property>
<property name="gender">property>
<union-subclass name="Pig" table="t_pig">
<property name="weight">property>
union-subclass>
<union-subclass name="Bird" table="t_bird">
<property name="height">property>
union-subclass>
class>
hibernate-mapping>
导出表后,产生两张子表,字表中包含父类的映射字段,存取方式一样不再复述
悲观锁不是hibernate的锁,这是数据库的update锁。Select * from item for update。Hibernate就是用的这种机制,在查询上上锁。
@Test
public void updateStock(){
Session session = HibernateUtils.getSession();
Transaction tx = session.beginTransaction();
try{
//使用悲观锁查询,如果一个请求在查询时,另一个请求被阻塞在外
Item item = (Item) session.load(Item.class, 1, LockOptions.UPGRADE);
item.setStock(item.getStock() - 2);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtils.closeResource(session);
}
}
悲观锁的性能比较低,因为查询也被锁住,我们乐观锁可以很好解决这个问题
通过设置版本号和查询版本号来解决这个问题
@Test
public void updateStock(){
Session session = HibernateUtils.getSession();
Transaction tx = session.beginTransaction();
try{
Item item = (Item) session.load(Item.class, 1);
item.setStock(item.getStock() - 2);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtils.closeResource(session);
}
}
根据不同需求来选择不同的策略来查询,后台生成的sql也不一样
many-to-one上的fetch=join
/**
* 多对一的单端抓取 many-to-one上的fetch=join
*/
@Test
public void fetch2(){
Session session = HibernateUtils.getSession();
try {
Emp emp = (Emp) session.load(Emp.class,1);
//发出一条两张表的连接查询把emp和team的数据都查询出来
System.out.println(emp);
Team team = emp.getTeam();
//不发sql
System.out.println(team);
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: select emp0_.emp_no as emp_no1_0_0_, emp0_.ename as ename2_0_0_, emp0_.birthday as birthday3_0_0_, emp0_.gender as gender4_0_0_, emp0_.address as address5_0_0_, emp0_.t_id as t_id6_0_0_, team1_.t_id as t_id1_1_1_, team1_.t_name as t_name2_1_1_, team1_.loc as loc3_1_1_ from t_emp emp0_ left outer join t_team team1_ on emp0_.t_id=team1_.t_id where emp0_.emp_no=?
Emp [empNo=1, ename=0-kobe0, birthday=2015-09-17 20:39:40.0, gender=1, address=洛杉矶]
Team [tId=1, tName=湖人0, loc=洛杉矶]
many-to-one上的fetch=select
/**
* 多对一的单端抓取 many-to-one上的fetch=select
*/
@Test
public void fetch1(){
Session session = HibernateUtils.getSession();
try {
Emp emp = (Emp) session.load(Emp.class,1);
//发出一条根据emp_no查询emp的sql
System.out.println(emp);
//不发sql
Team team = emp.getTeam();
//发出一条查询根据t_id查询球队的sql
System.out.println(team);
} catch (Exception e) {
e.printStackTrace();
}finally{
HibernateUtils.closeResource(session);
}
}
输出:
Hibernate: select emp0_.emp_no as emp_no1_0_0_, emp0_.ename as ename2_0_0_, emp0_.birthday as birthday3_0_0_, emp0_.gender as gender4_0_0_, emp0_.address as address5_0_0_, emp0_.t_id as t_id6_0_0_ from t_emp emp0_ where emp0_.emp_no=?
Emp [empNo=1, ename=0-kobe0, birthday=2015-09-17 20:39:40.0, gender=1, address=洛杉矶]
Hibernate: select team0_.t_id as t_id1_1_0_, team0_.t_name as t_name2_1_0_, team0_.loc as loc3_1_0_ from t_team team0_ where team0_.t_id=?
Team [tId=1, tName=湖人0, loc=洛杉矶]
一级缓存也叫Session的缓存,不能跨Session,如果Session关闭那么缓存数据也清掉。
二级缓存是SessionFactory级别的缓存,这个缓存能被所有的Session共享,可以跨Session,如果SessionFactory关闭,二级缓存随着消失。
<diskStore path=“java.io.tmpdir”/>
Ehcache配置:
属性 | 说明 |
---|---|
maxElementsInMemory | 缓存中对象的个数 |
eternal | Elements是否永久有效 |
TimeToIdleSeconds | 在对象失效前允许的闲置时间 |
TimeToLiveSeconds | 对象在缓存中存在的最大时间 |
OverFlowToDisk | 如果内存缓存满了就可以写在硬盘上 |
MaxElementsOnDisk | 硬盘上的对象的最大数量 |
diskPersisent | 是否在硬盘上永久有效 |
memoryStoreEvctionPolicy | LRC(最近最少使用),FIFO(先进先出) |
使用二级缓存的方法:get,load,iterator,不使用的list
在映射文件hbm.xml文件中添加配置
在系统配置文件cfg.xml文件中添加配置
使用collection-cache定义集合对象缓存,注意这里定义的是关联关系中的集合对象名,而不是关联模型类,更不是集合。
usage定义了缓存的种类:读写缓存、只读缓存等。
在ehcache.xml中添加自定义缓存设定,指定不同的缓存策略
二级缓存只能依赖仅使用OID进行查询,这一设定将对二级缓存的实用性大打折扣。
查询缓存可以有效解决上述问题
对要进行查询缓存的操作开始使用查询缓存设置
setCacheable(true)操作表明本次查询设定缓存区域为查询缓存区域,而不是二级缓存的常规区域。
注意:查询缓存的数据只能从查询缓存中获取,与二级缓存中其他区域的数据没有关系,因此每次都要设定使用查询缓存。