有关HIBERNATE

来源:互联网 发布:单身久了 知乎 编辑:程序博客网 时间:2024/04/27 19:47
 有关HIBERNATE

继承实现的三种策略
 单表继承。每棵类继承树使用一个表(table per class hierarchy)
 具体表继承。每个子类一个表(table per subclass)
 类表继承。每个具体类一个表(table per concrete class)(有一些限制)
 单表继承
 <discriminator column="discriminator_column" type="discriminator_type" />
 <subclass name="com.test.hibernate.Student">
  <property name="number" column="studentNumber"/>
 </subclass>

双向关联
  概念:双向关联允许通过关联的任一端访问另外一端。在Hibernate中, 支持两种类型的双向关联。
  一对多(one-to-many),Set或者bag值在一端, 单独值(非集合)在另外一端 。
  多对多(many-to-many),两端都是set或bag值。
例子(双向关联):group-user
<class name="com.test.hibernate.Group" table="TBL_GROUP">
 <id name="id" column="groupId"><generator class="native"></id>
 <set name="users" lazy="true" cascade="save-update" inverse="true">
    <key column="groupId"/>
  <one-to-many class="com.test.hibernate.User"/>
 </set>
</class>

<class name="com.test.hibernate.User" table="TBL_USER">
 <id name="id" column="userId"><generator class="native"/></id>
 <many-to-one name="group" column="groupId" outer-join="false"/>
</class>
例子:从Java代码看group-user双向关联的inverse
  概念:inverse用来标识双向关联的关联关系由哪一端维护。默认inverse的值为false,由主动方负责维护关联关系;如果设为true,则由反向一端维护关联关系。
  用例:我们假设已经有一个Group类的实例:adminGroup,现在我们要新增一个用户,并且将用户分配到adminGroup中。
  inverse="false",由主动方Group负责维护group-user的关联关系.
  User user = new User("Jak");
  adminGroup.getUsers.add(user);
  session.save(user); session.update(group);
  inverse="true",由Group的反向段User负责维护关联关系。
  User user = new User("Jak");
  user .setGroup(adminGroup); session.save(user);

持久化对象的生命周期(lifecycle)
Hibernate脏数据字段捡入
  检索一个用户,并将它的用户名更改为"Mary"
  Session session = sessionFactory.openSession();
  Transaction tx = session.beginTransaction();
  User user = (User) session.get(User.class, userId);
  user.setName("Mary");
  tx.commit();
  session.close();
持久化对象必须唯一
  一个Session中不能同时存在两个ID相同的持久化对象
 例如:id为userId的user_1对象已经存在Session中,这时如果Session中试图产生一个user_2对象!!
  Session session = sessionFactory.openSession();
  Transaction tx = session.beginTransaction();
  User user_1 = (User)session.get(User.class,userId);
  User user_2 = new User(userId,"Mary");
  session.update(user_2);
 最后将会产生异常:net.sf.hibernate.NonUniqueObjectException:
 a different object with the same identifier value was already associated with the session
 解决办法: 使用evict ()方法将user_1实例从session中去除。session.evict(user_1);

Hibernate查询
 概述:数据查询与检索是Hibernate中的一个亮点。相对其他ORM实现而言,Hibernate提供了灵活多样的查询机制。
 标准化对象查询(Criteria Query):以对象的方式进行查询,将查询语句封装为对象操作。优点:可读性好,符合Java 程序员的编码习惯。缺点:不够成熟,不支持投影(projection)或统计函数(aggregation)
 Hibernate语言查询(Hibernate Query Language,HQL):它是完全面向对象的查询语句,查询功能非常强大,具备继承、多态和关联等特性 。Hibernate官方推荐使用HQL进行查询。
 Native SQL Queries(原生SQL查询):直接使用数据库提供的SQL方言进行查询。
例子:标准化对象查询(Criteria Query)
 简单例子:查询用户名以"J"开头的所有用户。
 Criteria criteria = session.createCriteria(User.class);
        criteria.add(Expression.like("name","J%"));
        List users = criteria.list();
Hibernate语言查询(Hibernate Query Language,HQL)
 HQL用面向对象的方式生成SQL
 以类和属性来代替表和数据列
 支持多态
 支持各种关联
 减少了SQL的冗余
 HQL支持所有的关系数据库操作
 连接(joins,包括Inner/outer/full joins),笛卡尔积(cartesian products)
 投影(projection)
 聚合(Aggregation,max, avg)和分组(group)
 排序(Ordering)
 子查询(Subqueries)
 SQL函数(SQL function calls)

例子: Hibernate语言查询(Hibernate Query Language,HQL)
 简单例子:查询用户名以"J"开头的所有用户。
 Query query = session.createQuery(
   "from User user where user.name like 'J%'");
        List users = query.list();
 复杂例子:从User和Group中查找属于"admin"组的所有用户。
 Query query = session.createQuery(
   "from User user where user.group.name='admin'");

如果用传统的SQL则查询语句如下:
 select user.userId as userId, user.name as name, user.groupId as groupId, user.idCardId as idCardId 
 from TBL_USER user, TBL_GROUP group
 where (group.groupName='admin'  and user.groupId=group.groupId)

Hibernate最佳实践(Best Practices)
1、使用Configuration装载映射文件时,不要使用绝对路径装载。最好的方式是通过getResourceAsStream()装载映射文件,这样Hibernate会从classpath中寻找已配置的映射文件。
2、SessionFactory的创建非常消耗资源,整个应用一般只要一个SessionFactory就够了,只有多个数据库的时候才会使用多个SessionFactory。
3、在整个应用中,Session和事务应该能够统一管理。(Spring为Hibernate提供了非常好的支持)
4、将所有的集合属性配置设置为懒加载(lazy="true")。在hibernate2.x版本中,lazy默认值是"false",但hibernate3.x已经将lazy的默认改为"true"了。
5、在定义关联关系时,集合首选Set,如果集合中的实体存在重复,则选择List(在定义配置文件时,可以将List定义为bag),数组的性能最差。
6、在一对多的双向关联中,一般将集合的inverse属性设置为true,让集合的对方维护关联关系。例如:Group-User,由User来维护Group和User的关联关系。
7、HQL子句本身大小写无关,但是其中出现的类名和属性名必须注意大小写区分。
8、在非分布式架构中,不需要使用DTO来向上层传输数据。直接使用POJO的Entity就可以了。
9、如果要精通Hibernate,熟练掌握关系数据库理论和SQL是前提条件。