Hibernate part 14:查询及数据库并发事务


 

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

longcount=  (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>

 

 


 


 


 


 


 


 


 


 


 


 



 


 


 


 


 


 


 


 


















本站声明
本文转载自:http://mvplee.iteye.com/blog/2239488     作者:mvplee     发布日期:2015-08-31     本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。


 
© 2014-2016 ITdaan.com 粤ICP备14056181号