对象之间相互关联,toString()不要相互引用,java.lang.StackOverflowError 。
HQL查询
语法和SQL类似,可以实现SQL语句的大部分功能,支持链式编程风格,复杂查询直接使用SQL,Hiberante查询效率不高。
@Test public void test01() { Session session = HibernateUtils.openSession(); Transaction transaction = session.beginTransaction(); //匿名参数查询 Query query = session.createQuery(" from Customer where name=?"); query.setParameter(0, "孙艺珍"); List<Customer> list = query.list(); System.out.println(list); //有名参数查询 Query query = session.createQuery(" from Customer where name=:name"); query.setParameter("name", "孙艺珍"); List<Customer> list = query.list(); //参数为对象, 对象作为条件时按id查询 Customer c1 = (Customer) session.get(Customer.class, 1); Query query = session.createQuery("from Order where customer =?"); query.setEntity(0, c1); List<Order> list = query.list(); System.out.println(list); transaction.commit(); session.close(); }
通过对象导航的方式查询所有客户为孙艺珍的订单
@Test public void test06() { Session session = HibernateUtils.openSession(); Transaction transaction = session.beginTransaction(); Customer c1 = (Customer) session.get(Customer.class, 1); Query query = session.createQuery("from Order where customer.name =?"); query.setParameter(0, "孙艺珍"); List<Order> list = query.list(); System.out.println(list); transaction.commit(); session.close(); }
uniqueResult()如果返回1个或0个结果没有异常,返回0个结果时,结果为null,结果大于1会有异常,通常用于分组函数,sum、count、avg、max、min,返回值是long类型
long count= (Long) session.createQuery("select count(*) from Customer").uniqueResult();
命名查询,将HQL写道配置文件中,在Customer.hbm.xml中增加配置
<query name="findCustomerByName"> <![CDATA[from Customer where name=?]]> </query>
程序中通过xml配置中的name属性名称调用
List list = session.getNamedQuery("findCustomerByName").setParameter(0, "孙艺珍").list();
QBC(Query By Criteria)查询
通过面向对象的方式查询
查询所有的Customer数据
@Test public void test02() { Session session = HibernateUtils.openSession(); Transaction transaction = session.beginTransaction(); List<Customer> list = session.createCriteria(Customer.class).list(); System.out.println(list); transaction.commit(); session.close(); }
查询Customer为孙艺珍的数据
List<Customer> list = session.createCriteria(Customer.class).add(Restrictions.eq("name", "孙艺珍")).list();
查询1号客户的所有订单
Customer c1 = (Customer) session.get(Customer.class, 1); List<Customer> list = session.createCriteria(Order.class).add(Restrictions.eq("customer",c1)).list();
查询客户为孙艺珍的所有订单,不能采用对象导航的方式,也就是不能用“.”
List<Customer> list = session.createCriteria(Order.class).add(Restrictions.eq("customer.name", "孙艺珍")).list(); //org.hibernate.QueryException: could not resolve property: customer.name of: rock.lee.bean.Order
如果根据对象除id以外的属性查询,通过设置别名的方式
Customer c1 = (Customer) session.get(Customer.class, 1); List<Customer> list = session.createCriteria(Order.class).createAlias("customer", "c").add(Restrictions.eq("c.name", "孙艺珍")).list();
根据id排序
List<Customer> list = session.createQuery("from Customer order by id desc").list(); List<Customer> list = (List<Customer>) session.createCriteria(Customer.class).addOrder(org.hibernate.criterion.Order.desc("id")).list();
离线查询,在没有session的情况下创建查询对象,设置查询条件
DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Customer.class); detachedCriteria.add(Restrictions.like("name", "张%")); Session session = HibernateUtils.openSession(); Transaction transaction = session.beginTransaction(); List<Customer> customers = detachedCriteria.getExecutableCriteria(session).list(); System.out.println(customers); transaction.commit(); session.close();
SQL查询
查询表所有列数据时返回Object[]
@Test public void test03() { Session session = HibernateUtils.openSession(); Transaction transaction = session.beginTransaction(); SQLQuery sqlQuery = session.createSQLQuery("select * from customer"); List<Object[]> list = sqlQuery.list(); for (Object[] objs : list) { System.out.println(Arrays.toString(objs)); } transaction.commit(); session.close(); }将查询结果绑定到对象上,addEntity()是SQLQuery独有的,查询的列必须和Entity的字段对应
@Test public void test04() { Session session = HibernateUtils.openSession(); Transaction transaction = session.beginTransaction(); SQLQuery sqlQuery = session.createSQLQuery("select * from customer"); List<Customer> list = sqlQuery.addEntity(Customer.class).list(); System.out.println(list); transaction.commit(); session.close(); }
事务四大特性:ACID 原子性、一致性、隔离性、持久性
事务隔离引发的问题:
脏读:一个事务读取另一个事务为提交数据
不可重复读:一个事务读取到另一个事务已经提交的数据(update)
幻读:一个事务读取到另一个事务已经提交的数据(insert)
丢失更新:两个事务同时修改一条数据,后提交的数据覆盖了前一个事务提交的数据
事务隔离级别:
READ_UNCOMMITED 会发生所有隔离问题
READ_COMMITTED 会阻止脏读发生,但是会发生 不可重复读和幻读
REPEATABLE_READ 会阻止脏读和不可重复读,会发生幻读
SERIALIZABLE 以串行方式处理事务 , 同一时间只有一个事物,没有并发,没有隔离问题 (效率问题)
MySQL 数据库默认级别 REPEATABLE_READ , Oracle 数据库默认级别 READ_COMMITTED
hibernate 提供 hibernate.connection.isolation 属性, 用来修改数据库默认隔离级别 , 取值 1 2 4 8
1—Read uncommitted isolation
2—Read committed isolation
4—Repeatable read isolation
8—Serializable isolation
mysql 默认是4 , oracle 默认 2 hibernate.cfg.xml 修改隔离级别
<property name="hibernate.connection.isolation">2</property>
解决丢失更新的两种方式:
1、悲观锁:保证同一时间 只有一个人在修改,不会丢失更新 (缺点: 效率问题)
2、乐观锁:为数据添加一列版本字段,每次修改数据后 版本+1 (当版本不一致无法修改),不依赖数据库底层锁机制, 可以并发修改 。
<version name="ver"></version>