对象之间相互关联,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>