Hibernate的增删查改(事务)
内容已更新
新添加了4个查询方法:
分页查询
排序查询
聚合函数查询
投影查询
1 Hibernate中的事务
1.1 设置事务隔离级别
Hibernate中事务的隔离级别都是用字节存储的
二进制 十进制
read uncommitted 读未提交 0001 1
read committed 读已提交 0010 2
repeatable read 重复读 0100 4 mysql默认级别
serializable 可串行化 1000 8
配置数据库的隔离级别直接写十进制的值即可
在主配置文件(hibernate.cfg.xml)中配置数据库的隔离级别
<property name="hibernate.connection.isolation">4</property>
1.2 Hibernate管理事务的方法
//开启事务:
Transcation t= session.beginTranscation();
try{
//........写自己的代码(do som work....)
//提交事务:
t.commit();
}catch(Exception e){
//异常后:回滚事务
if(t!=null){
t.rollback();
}
}
1.3 Hibernate得到Session对象的方式
Configuration c= new Configuration();
c.Configure();//读hibernate.cfg.xml文件
SessionFactory factory= c.buildSessionFactory();
方式一:
factory.openSession();
方式二:
factory.getCurrentSession();
补充:要理解getCurrentSesssion()
//原理跟以前ThreadLocal<Connection>一样。
/**
* hibernate源码处理过程:
* 1.SessionFactory(接口)
* 2.该接口实现类(SessionFactoryImpl)
* 3.(搜索)getCurrentSession() :
* 方法如下: 配置的currentSessionContext值是thread(获取跟当前线程有管的session)
* public Session getCurrentSession() throws HibernateException {
if ( currentSessionContext == null ) {
throw new HibernateException( "No CurrentSessionContext configured!" );
}
return currentSessionContext.currentSession();
}
* 4.查看currentSessionContext。 该变量是一个CurrentSessionContext接口的实例
* 5.CurrentSessionContext接口实现类:ThreadLocalSessionContext:
*
* ThreadLocal<Map> sessionMap =new ThreadLocal<Map>();
*
*
等价于:ThreadLocal<<factory,session>> sessionMap =new ThreadLocal<<factory,session>>();
*
* @SuppressWarnings({"unchecked"})
private static void doBind(org.hibernate.Session session, SessionFactory factory) {
Map sessionMap = sessionMap();
if ( sessionMap == null ) {
sessionMap = new HashMap();
CONTEXT_TL.set( sessionMap);
}
sessionMap.put( factory, session);
}
*/
1.4 openSession()和getCurrentSession()区别(重点)
/*
* openSession()和getCurrentSession()
*
* 1.openSession()每次调用生成新的Session
* getCurrentSession()每次调用都使用的同一个session(与当前线程绑定的session)
*
* 2.openSession()使用不需要配置
* getCurrentSession()必须要配置,在主配置文件hibernate.cfg.xml中配置
* <property name="hibernate.current_session_context_class">thread</property>
* 3. openSession()使用之后可以关闭
* getCurrentSession()不能关闭
*
* 4.Session要线程安全建议使用getCurrentSession();
*
* 建议用getCurrentSession()
*/
1.5 HibernateUtils封装的工具类
package com.qf.utils;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtils {
private static SessionFactory sessionFactory=null;
static {
Configuration configuration = new Configuration();
configuration.configure();
sessionFactory = configuration.buildSessionFactory();
}
public static Session openSession() {
return sessionFactory.openSession();
}
public static Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
//openSession产生的session要关闭
public static void closeSession(Session session) {
session.close();
}
}
2.增删查改
2.1 增(插入)
@Test
public void testInsert1() {
//1.先得到
Session session = HibernateUtils.getCurrentSession();
Transaction t = session.beginTransaction();
try {
User user =new User();
user.setUser_name("皮皮虾");
user.setUser_pwd("123456");
session.save(user);
t.commit();
} catch (Exception e) {
// TODO: handle exception
t.rollback();
}
}
@Test
public void testInsert2() {
//1.先得到
Session session = HibernateUtils.getCurrentSession();
Transaction t = session.beginTransaction();
try {
User user =new User();
user.setUser_name("皮皮虾1");
user.setUser_pwd("1234567");
//参数1:实体类名称
session.save("User", user);
t.commit();
} catch (Exception e) {
// TODO: handle exception
t.rollback();
}
}
2.2 修改
@Test
public void testUpdate() {
Session session = HibernateUtils.getCurrentSession();
Transaction t = session.beginTransaction();
try {
//根据唯一表示来修改
User user =new User();
user.setUser_id(1);
user.setUser_name("皮皮虾2222");
user.setUser_pwd("123456");
session.update(user);
t.commit();
} catch (Exception e) {
// TODO: handle exception
t.rollback();
}
}
@Test
public void testSaveOrUpdate() {
Session session = HibernateUtils.getCurrentSession();
Transaction t = session.beginTransaction();
try {
//根据唯一表示来修改
User user =new User();
user.setUser_id(4);
//user.setUser_id(1);
user.setUser_name("皮皮虾3333");
user.setUser_pwd("1234564546");
//saveOrUpdate()根据唯一标识主键id决定是save还是update()
//能根据id查找到直接update
//没有id执行 save.
//如果设置了id,但是id在数据库中找不到,后台打印的是update,但是数据库中中插入了该数据
session.saveOrUpdate(user);
t.commit();
} catch (Exception e) {
// TODO: handle exception
t.rollback();
}
}
2.3 删除
@Test
public void testDelete() {
Session session = HibernateUtils.getCurrentSession();
Transaction t = session.beginTransaction();
try {
//根据唯一表示来修改
User user =new User();
user.setUser_id(1);
session.delete(user);
t.commit();
} catch (Exception e) {
// TODO: handle exception
t.rollback();
}
}
2.4 查询
2.4.1 第一种方式:OID
以oid(唯一标识)的形式进行查询(只能查询单条数据):
常见的:
//参数1:查询的类型:T.class 参数2:唯一标识id值
session.find(T.class,id);
session.get(T.class,id);
session.load(T.class,id);
示例:
@Test
public void test() {
//取Session
Session session = HibernateUtils.getCurrentSession();
Transaction t= session.beginTransaction();
try {
//参数1:查询的类型:T.class 参数2:唯一标识id值
//User user = session.find(User.class, 2);
//User user = session.get(User.class, 2);
User user = session.load(User.class, 2);
System.out.println("=2222==="+user);
t.commit();
} catch (Exception e) {
// TODO: handle exception
if (t!=null) {
t.rollback();
}
}
}
2.4.2 第二种方式:对象导航图查询
(常用于多表查询)
2.4.3 第三种方式:原生sql语句查询:
SQL(结构化查询语言 Structor Query Language)
Hibernate5.2以后用 session.createNativeQuery(sql语句);
Hibernate5.2以前用session.createSQLQuery(sql语句);
示例:
public void test02() {
//取session
Session session = HibernateUtils.getCurrentSession();
Transaction t= session.beginTransaction();
try {
//使用原生sql语句查询
//查询所有
//createNativeQuery是hibernate5.2版本之后建议用
/*NativeQuery<User> query=
session.createNativeQuery("select * from user", User.class);*/
//createSQLQuery是Hibernate5.2版本之前使用的,但是目前或者将来不会使用了
NativeQuery<User> query=session.createSQLQuery("select * from user");
//设置从第几个位置开始取数据
query.setFirstResult(0);
//设置每次最多取多少条数据
query.setMaxResults(4);
System.out.println("=--==="+query.list());
t.commit();
} catch (Exception e) {
// TODO: handle exception
if (t!=null) {
t.rollback();
}
}
}
备注:
//设置从第几个位置开始取数据
query.setFirstResult(0);
//设置每次最多取多少条数据
query.setMaxResults(4);
query.list()等价于query.getResultList() 得到查询的结果集合
原生sql的顺序及所有关键字及常见语句(mysql):
sql语句的书写顺序:
select * from 表名
where 条件
group by 列名
having 条件
order by 列名 asc/desc
limit start,size
1.having和where比较
where 在分组前过滤,
having在分组后过滤,可以加聚合函数(max,min,sum.count.avg),不能独立出现,必须分组后调用
2.sql执行顺序:
from 表名
where 条件
group by 列名
having 条件
order by 列名 asc/desc
limit start,size
select
3.模糊查询 like %代表任意字符 _代表一个字符 ,如果like后的值是字符串一定要用单引号
2.4.4 第四种方式:HQL查询(Hibernate Query Language) 重点重点来学
基于面向对象思想来查询。查询的是对象和对象的属性.
关键字不区分大小写。类和属性等区分大小写
以下方法获取多条数据:
query.list() query.getResultList()
以下方法获取单条数据:
query.uniqueResult()
1.基础查询
@Test
public void test01() {
//取Session
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
try {
//查询User表的所有数据
//从User类中找出所有的映射内容
//基本语法:from 包名+类名(如果整个程序中只有这么一个类,直接省略包名,默认查找该类)
//String HQL="from com.qf.domain.User";
String HQL="from User";//理解:找类其实找的是该类映射的数据库表的信息
//参数1:HQL语句 参数2:结果类型
Query<User> query = session.createQuery(HQL, User.class);
List<User> list = query.list();
System.out.println("=="+list);
transaction.commit();
} catch (Exception e) {
// TODO: handle exception
if (transaction!=null) {
transaction.rollback();
}
}
}
2.别名查询
//2.给类起别名查询
@Test
public void test02() {
//取Session
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
try {
//根据类别名来查询数据
//s是User类的别名,查询User类中的所有内容。select User类中的所有成员变量 from User
//简化版:select s from User s s代表整个User类,查询User类的所有
String HQL="select s from User s";
Query<User> query = session.createQuery(HQL, User.class);
System.out.println("===="+query.list());
transaction.commit();
} catch (Exception e) {
// TODO: handle exception
if (transaction!=null) {
transaction.rollback();
}
}
}
3.条件查询
方式一:?号占位,使用setParameter(position, value)赋值,位置从0开始
@Test
public void test03() {
//取Session
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
try {
String HQL="from com.qf.domain.User where user_id =? ";
Query<User> query = session.createQuery(HQL, User.class);
//参数1:?号的位置,从0开始
//参数2:value赋值
query.setParameter(0, 2);
System.out.println(query.uniqueResult());
transaction.commit();
} catch (Exception e) {
// TODO: handle exception
if (transaction!=null) {
transaction.rollback();
}
}
}
方式二:属性名称占位,使用setParameter(name,value)赋值
@Test
public void test04() {
//取Session
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
try {
//:user_id表示占位
String HQL="from com.qf.domain.User where user_id=:user_id";
Query<User> query = session.createQuery(HQL, User.class);
//参数1:表示属性名 ,参数2:属性名对应的值
query.setParameter("user_id", 2);
System.out.println("--===-----"+query.uniqueResult());
transaction.commit();
} catch (Exception e) {
// TODO: handle exception
if (transaction!=null) {
transaction.rollback();
}
}
}
4.分页查询
注意:在HQL中进行分页使用setFirstResult()和setMaxResult()进行分页数据填充,limit关键不要用。
//1.分页查询
@Test
public void TestByPage() {
Session session = HibernateUtils.getCurrentSession();
Transaction t = session.beginTransaction();
try {
//根据面向对象思想,基于类的对象和属性查找。
String hql="from com.qf.domain.Person";
Query<Person> query = session.createQuery(hql, Person.class);
query.setFirstResult(0);
//设置最多能查询到的数据的条数
query.setMaxResults(2);
System.out.println(query.list());
t.commit();
} catch (Exception e) {
// TODO: handle exception
if (t!=null) {
t.rollback();
}
}
}
5.排序查询
//注意:排序后的名称是属性名称 order by后跟的是属性名
//2.排序查询:
@Test
public void TestByOrder() {
Session session = HibernateUtils.getCurrentSession();
Transaction t = session.beginTransaction();
try {
//根据面向对象思想,基于类的对象和属性查找。
//uuid类型的主键可以排序
String hql="from com.qf.domain.Person order by IDCard desc";
Query<Person> query = session.createQuery(hql, Person.class);
System.out.println(query.list());
t.commit();
} catch (Exception e) {
// TODO: handle exception
if (t!=null) {
t.rollback();
}
}
}
6.聚合函数查询
结论: sum和count结果类型都是Long
max和min结果类型和所求列的类型一致
avg结果类型是Double
@Test
public void test03() {
Session session = HibernateUtils.getCurrentSession();
Transaction t = session.beginTransaction();
try {
//1.sum:结果类型是Long,跟所求列的类型无关
//String hql1="select sum(age) from com.qf.domain.Person";
//Query<Long> query = session.createQuery(hql1,Long.class);
//2.max,min结果类型跟所求的列的类型有关。
String hql2="select max(age) from com.qf.domain.Person";
String hql3="select min(age) from com.qf.domain.Person";
//Query<Integer> query = session.createQuery(hql4,Integer.class);
//3.avg结果类型是Dobule,跟所求的列的类型无关
String hql4="select avg(age) from com.qf.domain.Person";
//Query<Double> query = session.createQuery(hql5,Double.class);
//4.count结果类型是Long,跟所求的列的类型无关
String hql5="select count(*) from com.qf.domain.Person";
Query<Long> query = session.createQuery(hql5,Long.class);
System.out.println("====="+query.uniqueResult());
t.commit();
} catch (Exception e) {
// TODO: handle exception
System.out.println("-------"+e.getMessage());
if (t!=null) {
t.rollback();
}
}
}
7.投影查询
//投影查询:
//需求:前面查询的都是查询所有列。表示扫描整个表。
//实际情况中,可能只关注表中的其中几个列,并不是所有。 如果这种情况再去扫描整个表查数据,效率低下。
//1.查询Person类中的名称列name
@Test
public void test0001() {
Session session = HibernateUtils.getCurrentSession();
Transaction t = session.beginTransaction();
try {
//该语句中的name是属性名
String hql="select name from com.qf.domain.Person";
Query<String> query = session.createQuery(hql, String.class);
System.out.println(query.list());
t.commit();
} catch (Exception e) {
// TODO: handle exception
System.out.println("-------"+e.getMessage());
if (t!=null) {
t.rollback();
}
}
}
//2.查询Person类中的名称列name,address,查询多个列,返回结果类型是Object[]类型
@Test
public void test0002() {
Session session = HibernateUtils.getCurrentSession();
Transaction t = session.beginTransaction();
try {
//该语句中的name是属性名
String hql="select name,address from com.qf.domain.Person";
Query<Object[]> query = session.createQuery(hql, Object[].class);
//list: 30个 list的每一项Object[] ========name,address
for (int i = 0; i <query.list().size(); i++) {
Object[] objects = query.list().get(i);
System.out.println(objects[0]+"==="+objects[1]);
}
t.commit();
} catch (Exception e) {
// TODO: handle exception
System.out.println("-------"+e.getMessage());
if (t!=null) {
t.rollback();
}
}
}
//3.查询Person类中的名称列name,address 改进,返回值是指定的实体类类型Person(必须具有new Person(name,address)有参的构造方法)
@Test
public void test0003() {
Session session = HibernateUtils.getCurrentSession();
Transaction t = session.beginTransaction();
try {
//该语句中的name是属性名
String hql="select new Person(name,address) from com.qf.domain.Person";
Query<Person> query = session.createQuery(hql, Person.class);
System.out.println(query.list());
t.commit();
} catch (Exception e) {
// TODO: handle exception
System.out.println("-------"+e.getMessage());
if (t!=null) {
t.rollback();
}
}
}