Hibernate下的增删改查
概述:
关系--对象映射的中间件,属于开源ORM框架,是我们业务逻辑层中的调用数据库的中间件
演变:
jdbc---hibernater---mybatis
hibernate和mybatis区别?
1:hiberanter学习的难度要比mybatis要大,复杂度要高
2:hibernate不需要写sql语句,自动生成,而mybatis需要写sql语句进行数据操作
3:hibernate支持分页(API),而mybatis不支持分页(那是属于插件)
4:hibernate支持事务处理,而mybaits不支持事务处理(Spring)
5:hibernate支持一级缓存、二级缓存和查询缓存,而mybaits本身没有缓存(加载第三方缓存技术)
环境搭建步骤:
1:导包
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.3.3.Final</version> </dependency>
2:加载配置文件hibernate.cfg.xml(数据库连接信息)
3:需要增加映射文件(写的不是sql语句,写的是实体entity和表table中的字段、类型对应关系)
数据库工具类:
public class HibernateUitls { public static Session getSession() { // 获取数据库的连接工厂 // 从工厂中获取连接session Configuration config = new Configuration(); config.configure("hibernate.cfg.xml"); SessionFactory sf = config.buildSessionFactory();// 获取工厂 Session session = sf.openSession(); return session; } }
增删改查操作
/** * 测试hibernate增删改查 * @author lisi * @date 2018年8月20日 */ public class HibernateTest { /** * 查询操作---读操作 */ @Test public void query(){ Session session = HibernateUitls.getSession(); Note note = session.get(Note.class, 63);//根据主键查询 if (note != null) { System.out.println(note.getContext()); } } /** * 增加---写操作 */ @Test public void save(){ Session session = HibernateUitls.getSession(); Note note = new Note(); note.setId(3000); note.setContext("java20增加测试数1"); note.setLikeCount(10); note.setUserId(1); note.setPublishTime(new Date(System.currentTimeMillis())); Transaction ts = session.beginTransaction();//开启事务处理 session.save(note);//保存数据 ts.commit();//提交事物-- session.close();//关闭连接 } /** * 修改数据 */ @Test public void update(){ Session session = HibernateUitls.getSession(); // Note note = new Note(); Note note = session.get(Note.class, 3000); //note.setId(3000); note.setContext("java20增加测试数2"); Transaction ts = session.beginTransaction();//开启事务处理 session.update(note); ts.commit();//提交事物-- session.close();//关闭连接 } /** * 删除操作 * 1:先查询数据是否存在 * 2:如果存在,则删除,不存在,则不执行delete * 3:hibernate做的安全设置 */ @Test public void delete(){ Session session = HibernateUitls.getSession(); Note note = new Note(); note.setId(3000); Transaction ts = session.beginTransaction();//开启事务处理 session.delete(note); ts.commit();//提交事物-- session.close();//关闭连接 } }
Hibernate主键管理
策略生成的位置配置:
<id name="id" type="integer" column="id">
<generator class="identity"></generator>
</id>
1.sequence 序列
主要用于oracle数据库
2.identity 主键自增
主要用于mysql、SqlServer
主键自增
3.native
自动识别当前数据库的类型
如果数据库为oracle,则默认的ID生成策略为sequence
如果数据库为mysql等,则默认的ID生成策略为identity
4.increment
代表当前数据库表的主键ID,查询数据库ID最大值+1
5.uuid/hilo
采用UUID和hilo的算法,生成一个字符串,当成主键ID
6.assigned
是hibernate默认的主键生成策略,增加set方法
Hibernate查询操作
-
SQL:面向结构的查询 Structured Query Language(结构化)
select * from note 或者 SELECT * FROM NOTE
-
HQL:面向对象的查询 hibernater query language(对象化)
select userid(实体类中的属性名称) from Note(实体类名)
HQL和SQL区别?
- HQL是面向对象的查询,SQL是面向结构化的查询
- HQL查询时候对查询属性大小写比较敏感,SQL在查询的时候对属性的大小写依赖于我们的配置
- HQL支持count、sum、avg等,但是HQL不支持类型转换,比如日期转换、字符串转换
- HQL不建议使用left join,而SQL可以无条件的使用
- HQL在做查询的时候,如果是查询所有字段信息,则可以省略select *,直接使用from 实体类名
- HQL在查询的时候,使用的是类名和属性名,SQL查询的时候,使用的表名和字段名
- HQL和SQL在使用上,或者处理业务上,HQL只能进行简单操作,SQL可以进行复杂操作
结构化:
HQL查询
普通查询
1:查询所有的数据
2:根据条件进行查询
3:分页条件
4:统计个数
代码如下:
/** * hibernate普通查询 * @author lisi * @date 2018年8月21日 */ public class HQLTest { /** * 查询所有的数据 */ @Test public void query(){ Session session = HibernateUitls.getSession(); String hql = "from Note";//注意:这里的Note不是你的数据库表名,而是你的实体类名 Query query = session.createQuery(hql); List<Note> list = query.list();//获取查询结果集 //list.isEmpty() 只会判断list中的数据是否为空 //list != null && list.size() > 0 判断的是对象list是否存在,并且判断list中是否有数据 if (list != null && list.size() > 0) { for (int i = 0; i < list.size(); i++) { System.out.println("内容为:" + list.get(i).getContext()); } } } /** * 根据条件查询 * select * from note where userId = 3 */ @Test public void test2(){ Session session = HibernateUitls.getSession(); //jpa-style //String hql = "from Note where userId=?0";//?代表占位符,占位符下标是从0开始 String hql = "from Note where userId = :userid"; Query query = session.createQuery(hql); // query.setInteger(0, 3); // query.setParameter(0, 3); query.setParameter("userid", 3); List<Note> list = query.list();//获取查询结果集 if (list != null && list.size() > 0) { for (int i = 0; i < list.size(); i++) { System.out.println("内容为:" + list.get(i).getContext()); } } } /** * 分页查询 * * select * from note limit 0,3; */ @Test public void test3(){ Session session = HibernateUitls.getSession(); String hql = "from Note"; Query query = session.createQuery(hql); query.setFirstResult(1);//分页条件limit的第一个参数,下标是从0开始 query.setMaxResults(3);//分页条件limit的第二个参数,代表需要查询的条数 List<Note> list = query.list();//获取查询结果集 if (list != null && list.size() > 0) { for (int i = 0; i < list.size(); i++) { System.out.println("内容为:" + list.get(i).getId()); } } } /** * 统计个数 * select count(1) from note */ @Test public void test4(){ Session session = HibernateUitls.getSession(); String hql = "select count(0) from Note"; Query query = session.createQuery(hql); Long count = (Long) query.uniqueResult(); System.out.println("统计个数为:" + count); } }
Criteria查询
多条件查询、可以根据实体类属性的字段、排序、分组、分页、统计个数、and、or等
示例代码:
/** * 多条件查询 * @author likang * @date 2018年8月21日 */ public class CriteriaTest { /** * select * from note; */ @Test public void test1(){ Session session = HibernateUitls.getSession(); Criteria criteria = session.createCriteria(Note.class); List<Note> list = criteria.list(); if (list != null && list.size() > 0) { for (int i = 0; i < list.size(); i++) { System.out.println("内容为:" + list.get(i).getContext()); } } } /** * select * from note where userId = 3; * select * from note where userId = 2 and id = 2005; * select * from note where userId = 2 or id = 2005; * select * from note where userId = 2 or id = 2005 order by id desc/asc; */ @Test public void test2(){ Session session = HibernateUitls.getSession(); Criteria criteria = session.createCriteria(Note.class); // criteria.add(Restrictions.eq("userId", 2)); // criteria.add(Restrictions.eq("id", 2005)); criteria.add(Restrictions.or(Restrictions.eq("userId", 2), Restrictions.eq("id", 2005))); // criteria.addOrder(Order.desc("id")); criteria.addOrder(Order.asc("id")); List<Note> list = criteria.list(); if (list != null && list.size() > 0) { for (int i = 0; i < list.size(); i++) { System.out.println("内容为:" + list.get(i).getContext()); } } } /** * hibernate5新特性写法: * select * from note where userId = 3; */ @Test public void test3(){ Session session = HibernateUitls.getSession(); CriteriaBuilder crb = session.getCriteriaBuilder(); CriteriaQuery<Note> criteria = crb.createQuery(Note.class); Root<Note> root = criteria.from(Note.class); criteria.where(crb.equal(root.get("userId"), 1)); Query<Note> query = session.createQuery(criteria); List<Note> list = query.list(); if (list != null && list.size() > 0) { for (int i = 0; i < list.size(); i++) { System.out.println("内容为:" + list.get(i).getContext()); } } } }
NativeSQL查询
原生查询、支持sql语句的查询
示例代码:
/** * 原生sql语句查询 * @author lisi * @date 2018年8月21日 */ public class NativeSQLTest { @Test public void test1(){ Session session = HibernateUitls.getSession(); String sql = "select * from note"; // SQLQuery query = session.createSQLQuery(sql); // List<Object[]> list = query.list(); // if (list != null && list.size() > 0) { // for (Object[] obj : list) { // System.out.println(obj[1]); // } // } SQLQuery query = session.createSQLQuery(sql); query.addEntity(Note.class);//在进行遍历之前,提前进行数据映射转换 List<Note> list = query.list(); if (list != null && list.size() > 0) { for (int i = 0; i < list.size(); i++) { System.out.println("内容为:" + list.get(i).getContext()); } } } /** * hibernate5新特性写法: */ @Test public void test2(){ Session session = HibernateUitls.getSession(); String sql = "select * from note where userId = 3"; NativeQuery query = session.createNativeQuery(sql); query.addEntity(Note.class);//在进行遍历之前,提前进行数据映射转换 List<Note> list = query.list(); if (list != null && list.size() > 0) { for (int i = 0; i < list.size(); i++) { System.out.println("内容为:" + list.get(i).getContext()); } } } }
Hibernate注解应用
类上面注解:
@Entity
@Table(name="note")
方法属性注解:
@Id @Column(name="数据库中字段主键") @GeneratedValue(generator="identity") private int id;//主键
其它字段:
@Column(name="数据库中字段名称")
修改hibernate.cfg.xml配置文件:
<mapping class="com.xdl.entity.Note"/>
Hibernate特性
延迟加载
hibernate中的API,有一些是具有延迟加载的特性,对象在调用的时候,才会进行数据加载(什么时候调用,什么时候加载)
get、list方法,不具有延迟加载特性
load、find方法,具有延迟加载特性
问题:
...... no session
问题请求:
接口请求--->web.xml--->action--->service--->dao(session关闭)--->view
解决:
接口请求--->web.xml--->action--->service--->dao(session不关闭)--->view--->关闭session(事务spring)
缓存(性能优化)
缓存:对象在第一次使用的时候,是进行数据加载(需要查询数据库),下一次查询同样条件的数据,则直接从缓存中获取,而并发查询数据库(速度快、减轻数据库服务器压力)
-
一级缓存
自动开启,不需要做任何的配置和修改 特点: session独享
-
二级缓存
特定: session共享
-
查询缓存
持久化(session)
-
临时状态
可以被JVM进行垃圾回收
-
持久化状态
不能更直接被JVM回收,可以先变成其它两种状态之后,才会进行垃圾回收
-
游离状态
可以被JVM进行垃圾回收
Spring+Hibernate整合
整合结构:
整合步骤:
1:导包
hibernate-core
2:导入spring包
3:加载spring和hibernate配置文件
4:在spring的配置文件中,增加数据库的连接信息和事务管理
5:将原来的工程进行改造---jdbc实现类注释,增加一个hibernate实现类
6:实现接口方法
7:部署、启动、访问
核心代码:
applicationContext.xml:
<!-- 加载hibernateTemplate --> <bean id="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> <!-- 加载sessionFacotory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> <property name="dataSource" ref="c3p0"></property> <property name="configLocations" value="classpath:hibernate.cfg.xml"></property> </bean> <!-- 处理事务 --> <bean id="txManger" class="org.springframework.orm.hibernate5.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <!-- 事务支持注解驱动 --> <!-- proxy-target-class:属性默认为false,则代表是使用jdk本身的代理(静态代理) true:则代表使用的是cglib代理(动态代理模式) --> <tx:annotation-driven transaction-manager="txManger" proxy-target-class="true"/>
HibernateServiceImpl.java:
@Repository public class HibernateServiceImpl implements INoteService{ @Resource private HibernateTemplate hibernateTemplate; @Override public List<Note> queryNoteList(int userid) { DetachedCriteria dCriteria = DetachedCriteria.forClass(Note.class); dCriteria.add(Restrictions.eq("userId", userid)); List<Note> list = (List<Note>) hibernateTemplate.findByCriteria(dCriteria); String hql = "from Note where userId=:userId"; List<Note> list1 = (List<Note>) hibernateTemplate.findByNamedParam(hql, "userId", userid); return list1; } @Override public int deleteNotesById(int id) { Note note = hibernateTemplate.get(Note.class, id); if (note != null) { hibernateTemplate.delete(note); return 1; } return 0; } }
如果有删除操作,需要在删除的action的类头上加上标注,将只读模式关闭
@Transactional(readOnly=false)//将只读模式进行关闭
DeleteAction.java: