Hibernate的最佳实践

Reading time ~14 minutes

此文章为原创文章,引用请标记文章出处: Hibernate的最佳实践
  • 多对多连接可以转为使用两个指向中间表的一对多的连接比较好

  • 在做关系尽可能使用单向关联,不要使用双向关联

  • 在大项目中,(数据量如果超过百万条的项目),使用Hibernate可以酌情考虑一下几个原则:

  • 1.不要使用对象关联,尽可能用冗余字段来替代外键(使用冗余字段所带来的问题就是在修改时必须修改所有的冗余字段)

  • 2.当某些操作对系统的性能带来瓶颈时,这些操作也许直接使用JDBC方式会更好。如:查询数据不再使用HQL,而使用SQL查询,如果涉及缓存,自己根据情况加入相应的缓存,而不是使用Hibernate的缓存。

  2.1如果查询的是单张数据库表的信息

Session =HibernateUtil.openSession();
List<Student> stus=session.createSQLQuery("select * from t_stu where name like ?")
      .addEntity(Student.class)
      .setParameter(0,"%莫%")
      .list();

  2.2如果查询的是多张数据库表的关联信息

Session session=null;
try{
      session=HibernateUtil.openSession();
      List<Object[]> stus=session.createSQLQuery("select (stu.*),(cla.*),(spe.*) from "+
           "t_stu stu left join t_classroom cla on(stu.cid=cid.id) "+
           "left join t_special spe on(spe.id=cla.spe_id) where stu.name like ?")
           .addEntity("stu",Student.class)
           .addEntity("cla",Classroom.class)
           .addEntity("spe",Special.class)
           .setParameter(0,"%莫%")
           .setFirstResult(0).setMaxResults(10)
           .list();
           Student stu=null;
           Classroom cla=null;
           Special spe=null;
           for(Object[] obj:suts){
                 stu=(Student)obj[0];
                 stu=(Classroom)obj[1];
                 stu=(Special)obj[2];
 System.out.println(stu.getName()+","+cla.getName()+","+spe.getName());
           }
}

  2.3使用DTO(只用于传输属性的对象,并不用于与数据库的交互)代替类对象:

Session session=null;
try{
      session =HibernateUtil.openSession();
      List<StudentDto> stus=session.createSQLQuery("select stu.id as sid,stu.name as name,"+
           "stu.sex as sex,cla.name as cname,spe.name as spename from "+
           "t_stu stu left join t_classroom cla on(stu.cid=cls.id) "+
           "left join t_special spe on(spe.id=cls.spe_id) where stu.name like ?")
 .setResultTransformer(Transformers.aliasToBean(StudentDto.class))//将结果集进行一次封装,封装成StudentDto对象,方便service层代码的取用
           .setParameter(0,"%莫%")
           .setFirstResult(0).setMaxResult(10)
           .list();
      for(StudentDto sd:stus){
           System.out.println(sd);
      }
}
  • 就像在 JDBC 编程中一样,应该总是用占位符 “?” 来替换非常量值,不要在查询中用字符串值来构造非常量值。你也可以考虑在查询中使用命名参数。

  • 不要自己来管理 JDBC 连接:

Hibernate 允许应用程序自己来管理 JDBC 连接,但是不推荐。如果你不能使用 Hibernate 内建的 connections providers,那么考虑实现自己来实现org.hibernate.connection.ConnectionProvider。

  • 考虑使用用户自定义类型(custom type):

如果持久化的类没有提供映射操作需要的存取方法,那么该类才可以通过实现org.hibernate.UserType接口,来实现类属性类型与 Hibernate type之间的相互转换。

  • 当异常发生的时候,必须要回滚Transaction ,关闭 Session。

  • 对于关联来说,若其目标是无法在第二级缓存中完全缓存所有实例的类,应该使用代理(proxies)与/或具有延迟加载属性的集合(lazy collections)。若目标是可以被缓存的,尤其是缓存的命中率非常高的情况下,应该使用lazy=”false”

jdk-timer、spring-task、quartz的比较

这篇文章将简单介绍目前常用的定时任务框架! Continue reading

小岛经济学-读书笔记

Published on May 10, 2018

java常见的http请求库

Published on May 05, 2018