`

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类型

		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>
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics