Hibernate几个重点问题

 

事务处理:

   事务就是一组相互依赖的操作,要么全成功,要么全部失败。比如:A转账到B100,必须A账户减少100B账户同时增加100,两个都成功才可以。在程序里面不能将事务设置成自动提交(查询除外),在JDBC里面是用ConnectionsetAutoCommit方法来实现的,在操作之前设置成false,在最后一步commit,在catch里面回滚。

   事务不能读到没有提交的,或者已经取消的,事务隔离级别一般由数据库控制,有四种,一般选用read committedmysql默认是repeattable read.

  Repeatable read:在同一个事务中两次读到同一个记录,应该得到一样的结果,其实就是说,一个事物读到一条记录,但是还没提交,另一个事务同时来读,要修改它时,必须等到之前那个事务提交了,该事务才能修改,但是是可读的。

  程序中一般是乐观锁实现。

  悲观锁很影响性能,他会在发sql时加上for updateselect … for update。这样一查出来就被锁定。别的事务可读,但是不可修改。直到他提交。悲观锁就是认为,事务的数据总会受到别的事务的影响,就一开始就上锁。

 

  Read Committed

   要解决non-repeatable read的问题。用到乐观锁和悲观锁来实现。

   出现的问题:例如:账户a,取出余额,计算后再放回数据库,但是取出余额到放回数据库的过程中,有另一个事务改了这个a的值,这时,这个事务再放回数据库就冲掉了那个数据。

实现就是乐观锁:

   注解版本解决方法:在实体类里面有

        private int version; getVersion()方法上加注解@Version;即可。在保存数据时,这个字段不用管,由hibernate自动维护。此时:第一个session load,第二个session load相同的,然后第一个事务修改数据,第二个事务修改数据,最后第一个session提交,第二个session提交。这时,第二个session就会被报错。因为第一个session提交后,version改变了,第二个session提交时发现这个version不是它load数据的那个值,就会报错了。这个事务就会回滚。出现这种情况,可以稍等一会再提交。

 

----------关系到hibernate的性能问题

    第一个性能问题:分页,一条50条,在同一个session中时,不断翻页,这个session会不断增加记录。要记得session.clear();(这种情况比较少)。

    Java在语法上是没有内存泄露的。因为有垃圾回收器会清理,但是打开资源时,没有关闭,是可能造成内存泄露的。

    1+N问题:

      一个category对应几个topic,是一对多关系。循环查询topic时候,会把每个topic关联的category都查询出来,发了一堆sql语句。但是本意只是取topic。这是因为fetchType=eager.因为hql语句from Topic就只发一条,但是关联起来,会from Category where id=。。。。。。就变成发N条。因此叫1+N。就是说本来只发一条,结果发了1+N条。

解决方案:在@ManyToOnefetch=FetchType.LAZY)这是说不要立即取,不是就不能取了,用到的时候再取。

    但是查Category的语句什么时候发?查的时候发就是t.getCategory.getName()时发。

        第二种是用createCriteria方法不用createQuery()

        第三种解决方法是:在被关联的Category类上面加上@BatchSize(size=5),就是关联取时不要取完,一次取5条,取完所有数据。BatchSize比较少用。

 

关联关系的crud:

    存group,useruser有外键是group,正常情况,设关联关系,存group再存user是没有问题的。但是只存user希望存user时级联的存进group是会报错的。想级联的能保存,需要设置:cascadeall是说crud都级联,persist是仅保存时级联。具体的设置方法是

@ManyToOne(cascade={CascadeType.ALL});或者ALL换成PERSIST

(但是cascade只是写起来方便,还是按照默认的手动存的好。)

 一个写法:@OneToMany(mappedBy=”group”,cascade={CascadeType.ALL})

    manytoone取多的时候是get出来的,默认的会将一的一方取出来。就是取某个user会默认把他所在的组取出来。

    但是取一的一方,GROUP时,对应的users默认的就不会被取出来。即使CascadeType.ALL也不会取出来。Cascade就是crudr去掉的,rfetchType对应的。也就是说多对一取多时fetchTypeeager的。

   改:

    Load出来useruser.setName更新,user.getGroup.setName()会发两条语句,更新usergroup

   删:

    Usergroup,删除u1,如果设置的cascadeType.ALL,就会级联的删,将所有的都删掉。想删除的话,最好先把关联关系设置为null,就可以删除了。默认的是哪一项?会级联删除吗?删除最好用hql就是session.createQuery(“delete from User u where u.id=?”).executeUpdate();

这样删除比较精确;如果想删除group:先load出来group,如果设置了关联ALL会级联删除,最好是先循环取出user去掉关联关系再删除。

 

Hibernate的缓存:

  每开一个session它自己是有缓存的,这一个session里面两次getName是不会再发sql语句的。但是两个session先后都取同一个get Name时,相互之间缓存就不能互取,就会发两次sql语句。

   这就用到二级缓存,就是sessionFactory的缓存。

   <property name=”cache.use_second_level_cache”>true</property>

   <property name=”cache.provider_class”>org.hibernate.cache.EhCacheProvider</property>

   这两个配置后,还需要:一个ehcache.xml这个是ehcache真正的配置文件,规定怎么用cache,例子文件去etc下面找ehcache.xml这个文件,拷贝到src下面即可。

   Cache的配置:最多放多少个对象,缓存中的对象是否永存,idle空闲多久后被清除。timeToLive放进缓存后多久必须被销毁了。有默认的配置项,使用即可。

但是只有:

     经常被访问;改动不大;数据量不大的数据才适合放进缓存中。

     例如:用户权限。改动不大,数量也不大,又常被访问。

           组织机构;

 

配置好后:那些需要放入二级缓存的类还要配置一下,在annotation方式中是配

@Cache(usage=CacheConcurrencyStrategy.READ_WRITE); (读写最常用,read_only很少用)

不配置的话,这个类是不会被放入二级缓存中去的。

 

还有两个注意点:需要ehcache.jar包,这个包用的日志系统是apache的,需要加入:commons-logging.jar文件。

  此时,两个session同时去load一个对象,getName时就不会发两次SQL语句了。

 

  默认:load会使用二级缓存,就是查询一个对象时,它会先去二级缓存里里面找,iterator默认也是用二级缓存。

  List默认往二级缓存里面加数据,但是查询的时候不用。(就是查询不查二级缓存,但是查询出来,放二级缓存里面)。

        以上缓存是load时用缓存,或者用 get得到时,但是用hql查询时,还是不会用缓存的,要用的话还得配置查询缓存。

---查询缓存:

   打开查询缓存:查询缓存是依赖于二级缓存的,所以上面的二级缓存必须打开。

     <property name=”cache.use_query_cache”>true</property>

   在程序中要:

     session.createQuery(“from Category”).setCacheable(true).list();

        关键是setCacheable(true)//使用查询缓存。

双向一对多关联详解:

   从一到多的方向控制时,加set标签,子标签有one-to-manykey是说多的一方用哪个字段进行关联,inverse设置为true表示多的一方来控制这种关联关系,默认是false,一般一的一方设置为true,多的一方不用配置这个选项。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值