Hibernate之稍稍进阶
一、持久化类概述
-
什么是持久化类?
- 持久化:讲内存中的一个对象持久化到数据库中的过程,Hibernate框架就是用来进行持久化的框架.
- 持久化类:一个Java对象与数据库建立了映射关系,那么这个类在Hibernate中被称为持久化类。
-
持久化类的编写规则
- 对持久化类提供一个无参的构造方法
- Hibernate底层需要使用反射生成实例
- 属性需要私有,对私有属性提供public的 get和set方法
- Hibernate中获取,设置对象的值
- 对持久化类提供一个唯一标识ID与数据库主键对应
- Java中通过对象的地址区分是否是同一个对象,数据库中通过主键确定是否是同一个记录,在Hibernate中通过持久类的ID的属性区分是否是同一个对象。
- 持久化类的属性尽量使用包装类类型,因为基本的数据类型默认是0 ,那么0 就有很多的歧义。包装类的类型,默认值是null
- 持久化类不要使用final进行修饰
- 延迟加载本身是Hibernate的一个优化的手段,返回的是一个代理对象(javassist可以对没有实现接口的类产生代理,使用了非常底层的字节码增强技术,继承这个类进行代理)。如果不能被继承,不能产生代理对象,延迟加载也就失效了。
- 对持久化类提供一个无参的构造方法
-
持久化类的三种状态
- 瞬时态:不被session管理且在数据库中没有没有关联的记录,且没有唯一标识ID
- 持久态:在瞬时态的基础上被session所管理,并且有了唯一标识的ID
- 托管态:在持久态的基础之上,被session释放就变成了持久态对象
@Test //三种状态的区分区分 public void test01() { Session session = HibernateUtils.getSession(); Transaction transaction = session.beginTransaction(); Book book = new Book(); book.setBname("我是一个天才!"); //瞬时态对象:没有设置id session.save(book); //持久态对象:有ID 且被管理 transaction.commit(); session.close(); System.out.println(book);//瞬时态对象:session已经关闭,且有ID }
二、再谈主键
-
主键的分类
在数据库中,主键被分为自然主键以及代理主键,自然主键是指主键的本身就是表中的一个字段,比如人口信息表中,身份证是唯一的,就可以当做主键,这就被称为自然主键;代理主键是指主键的本省不是表中的一个字段,而是自己添加的一个主键。前边的Book表所使用的就是代理主键。在开发中应尽量使用代理主键,因为方便以后修改。
-
主键的生成策略
- 在配置持久化类与数据库表之间的映射的时候,需要配置主键的生成策略,Hibernate提供了很多的主键生成策略,下边举例一些比较常用的主键生成策略。
- increment:Hibernate中提供的自动增长机制,使用short、int、 long类型的主键,在单线程的程序中使用。
- identity:适用于short、int、long类型的主键,使用的是数据库底层的自动增强机制,适用于有自动增强机制的数据库。
- sequence:使用与short、int、long类型的主键,采用的是序列化的方式。
- uuid:使用与字符串类型的主键,使用hibernate中随机的方式生成字符串的主键。
- native:本地策略,可以在identity和sequence之间进行自动切换。
- assigned:Hibernate放弃外键的管理,需要通过手动编写代码或者用户自己设置主键。
- foreign:外部的。一对一的一种关系映射的情况下使用。
- 在配置持久化类与数据库表之间的映射的时候,需要配置主键的生成策略,Hibernate提供了很多的主键生成策略,下边举例一些比较常用的主键生成策略。
三、Hibernate的关联映射
-
级联操作
-
未开启级联操作的代码:
@Test // 保存2个客户 和 3个联系人 并且建立好关系 public void demo1(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); // 创建两个客户 Customer customer1 = new Customer(); customer1.setCust_name("張三"); Customer customer2 = new Customer(); customer2.setCust_name("李四"); // 创建三个联系人 LinkMan linkMan1 = new LinkMan(); linkMan1.setLkm_name("凤姐"); LinkMan linkMan2 = new LinkMan(); linkMan2.setLkm_name("如花"); LinkMan linkMan3 = new LinkMan(); linkMan3.setLkm_name("旺财"); // 设置关系: linkMan1.setCustomer(customer1); linkMan2.setCustomer(customer1); linkMan3.setCustomer(customer2); customer1.getLinkMans().add(linkMan1); customer1.getLinkMans().add(linkMan2); customer2.getLinkMans().add(linkMan3); // 保存数据: session.save(linkMan1); session.save(linkMan2); session.save(linkMan3); session.save(customer1); session.save(customer2); tx.commit(); }
-
开启级联操作之后:
@Test /** * 级联保存或更新操作: * * 保存客户级联联系人,操作的主体是客户对象,需要在Customer.hbm.xml中进行配置 * * <set name="linkMans" cascade="save-update"> */ public void demo3(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); Customer customer = new Customer(); customer.setCust_name("赵洪"); LinkMan linkMan = new LinkMan(); linkMan.setLkm_name("如花"); customer.getLinkMans().add(linkMan); linkMan.setCustomer(customer); session.save(customer); tx.commit(); }
- 级联:操作一个对象的时候,是否会同时操作其关联的对象。开启级联操作之后,可以简化代码,避免很多重复的代码。
- 开启级联的方法,在持久化类的配置文件中开启:
<!-- casade:开启级联操作 --> <set name="linkMans" cascade="save-update"> ... </set>
-
四、查询
-
OID查询
Hibernate根据对象的OID(主键)进行检索
Customer customer = session.get(Customer.class,1l);
Customer customer = session.load(Customer.class,1l);
-
HQL
HQL查询:Hibernate Query Language,Hibernate的查询语言,是一种面向对象的方式的查询语言,语法类似SQL。通过session.createQuery(),用于接收一个HQL进行查询方式。
@Test public void demo2() { Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); // 简单的查询 Query query = session.createQuery("from Customer"); List<Customer> list = query.list(); for (Customer customer : list) { System.out.println(customer); } tx.commit(); }
@Test public void demo3() { Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); List<Customer> list = session.createQuery("from Customer c").list; for (Customer customer : list) { System.out.println(customer); } tx.commit(); }
public void demo4() { Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); List<Customer> list = session.createQuery("from Customer order by cust_id").list(); List<Customer> list = session.createQuery("from Customer order by cust_id desc").list(); for (Customer customer : list) { System.out.println(customer); } tx.commit(); }
@Test public void demo5() { Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); // 一、按位置绑定:根据参数的位置进行绑定。 Query query = session.createQuery( "from Customer where cust_source = ? and cust_name like ?"); query.setParameter(0, "小广告"); query.setParameter(1, "李%"); List<Customer> list = query.list(); // 二、按名称绑定 Query query = session.createQuery("from Customer where cust_source = :aaa and cust_name like :bbb"); query.setParameter("aaa", "朋友推荐"); query.setParameter("bbb", "李%"); List<Customer> list = query.list(); for (Customer customer : list) { System.out.println(customer); } tx.commit(); }
@Test public void demo6() { Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); List<Customer> list = session.createQuery("select new Customer(cust_name,cust_source) from Customer").list(); for (Customer customer : list) { System.out.println(customer); } tx.commit(); }
@Test public void demo7() { Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); Query query = session.createQuery("from LinkMan"); query.setFirstResult(20); query.setMaxResults(10); List<LinkMan> list = query.list(); for (LinkMan linkMan : list) { System.out.println(linkMan); } tx.commit(); }
@Test public void demo8() { Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); // 聚合函数的使用:count(),max(),min(),avg(),sum() Object object = session.createQuery("select count(*) from Customer").uniqueResult(); System.out.println(object); // 分组统计: List<Object[]> list = session.createQuery("select cust_source,count(*) from Customer group by cust_source") .list(); for (Object[] objects : list) { System.out.println(Arrays.toString(objects)); } tx.commit(); }
-
QBC
QBC查询:Query By Criteria,条件查询。是一种更加面向对象化的查询的方式。
@Test public void demo1(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); // 获得Criteria的对象 Criteria criteria = session.createCriteria(Customer.class); List<Customer> list = criteria.list(); for (Customer customer : list) { System.out.println(customer); } tx.commit(); }
@Test public void demo2(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); Criteria criteria = session.createCriteria(Customer.class); criteria.addOrder(Order.asc("cust_id")); // 升序 criteria.addOrder(Order.desc("cust_id")); // 降序 List<Customer> list = criteria.list(); for (Customer customer : list) { System.out.println(customer); } tx.commit(); }
@Test public void demo3(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); // 分页查询 Criteria criteria = session.createCriteria(LinkMan.class); criteria.setFirstResult(10); criteria.setMaxResults(10); List<LinkMan> list = criteria.list(); for (LinkMan linkMan : list) { System.out.println(linkMan); } tx.commit(); }
@Test /** * 条件查询 */ public void demo4(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); // 条件查询 Criteria criteria = session.createCriteria(Customer.class); // 设置条件: /** * = eq * > gt * >= ge * < lt * <= le * <> ne * like * in * and * or */ criteria.add(Restrictions.eq("cust_source", "小广告")); criteria.add(Restrictions.or(Restrictions.like("cust_name", "李%"))); criteria.add(Restrictions.like("cust_name", "李%")); List<Customer> list = criteria.list(); for (Customer customer : list) { System.out.println(customer); } tx.commit(); }
@Test public void demo5(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); Criteria criteria = session.createCriteria(Customer.class); /** * add :普通的条件。where后面条件 * addOrder :排序 * setProjection :聚合函数 和 group by having */ criteria.setProjection(Projections.rowCount()); Long num = (Long) criteria.uniqueResult(); System.out.println(num); tx.commit(); }
@Test public void demo6(){ DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Customer.class); detachedCriteria.add(Restrictions.like("cust_name", "李%")); Session session = HibernateUtils.getCurrentSession(); Transaction transaction = session.beginTransaction(); Criteria criteria = detachedCriteria.getExecutableCriteria(session); List<Customer> list = criteria.list(); for (Customer customer : list) { System.out.println(customer); } transaction.commit(); }
-
SQL
@Test public void demo1(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); /*SQLQuery sqlQuery = session.createSQLQuery("select * from cst_customer"); List<Object[]> list = sqlQuery.list(); for (Object[] objects : list) { System.out.println(Arrays.toString(objects)); }*/ SQLQuery sqlQuery = session.createSQLQuery("select * from cst_customer"); sqlQuery.addEntity(Customer.class); List<Customer> list = sqlQuery.list(); for (Customer customer : list) { System.out.println(customer); } tx.commit(); }