卧龙会:软件Hibernate session开启与数据库物理连接的时间关系

文|原创:卧龙会 Arivn

先说结论:

spring openSession获取到的是hibernate session,并没有实际获取绑定数据库连接。

不到最后一刻,不操作db就不会获取实际的数据库连接。当第一次操作db时,hibernate session 才会绑定数据库物理连接。这样降低了session使用数据库连接时间片段,最大化的利用链接资源。

所以spring连接打开的session是hibernate Session,原创微信公众号:卧龙会IT技术。并不是实际数据库连接,可放心使用(提前Open hibernate Session 对数据库链接无消耗,所以spring filter才能帮助用户提前打卡session)

注:以下是基于hibernate和spring集成的前提下进行的。

一般spring的事物是配置在service上,所以来说service和controller上的情况

1

service 层情况

绑定数据库物理连接是在第一次操作数据库的时候发生。操作数据库包括查询,修改,删除,新增,当然还有事物。在service中后续的db操作继续使用第一次绑定的数据库连接,直到service方法退出结束。

对于非事物的查询(PROPAGATION_SUPPORTS)

不管你在service查询前做了什么复杂的业务,都不会绑定数据库链接

如下代码:

对于事物。开启事物时打开链接(PROPAGATION_REQUIRED)

进入方法就绑定了数据库链接,所以事物里面的逻辑单元应该精简,不要有太多和事物无关的逻辑。比如提交一个http请求,在请求中会浪费掉数据库链接的时间

service方法中调用内部其他方法

只会绑定一次数据库连接,第二次操作DB使用的是第一次操作DB绑定的链接,同样会把事物特性传递下来。

注意:上面的代码 baseDAO.save(bean)和 this.saveOptLog(id)并不会触发真实的保存和提交。事物和自动提交是加在service层,getById不会触发事物的开启和自动提交。如果saveOptLog是其他servcie中注入的方法会自动开启的事物,但是继续使用同一连接,如下代码:

2

controller 情况

每调用一次service都会绑定一个数据库物理连接,并且执行完后释放掉。

原因:service是spring注入进来的代理service,有事物增强处理。

如果是处理重复业务数据,preparestatement不一定会生效。

原因:controller重复调用service的方法绑定到的数据库连接不一定是同一个,preparestatement是基于同一连接生效的。如果preparestatement要生效需要放在service内处理。

3 控制代码划分规则建议

一般来说service根据模块功能和解耦,里面可能会包含部分的业务逻辑控制代码;controller本身是控制层,也会包含部分逻辑控制代码。那么逻辑控制代码怎么区分是方在service层还是controller呢?

如果是处理比较复杂的业务请求,并且可能消耗的时间比较久(正常情况应该走MQ进行异步处理,但这个地方讨论不能走异步必须面对的情况)。需要把消耗时间的业务逻辑控制上浮,放在controller中处理,即使是同一service。

erivce和controller的规则:

1 根据模块功能划分,并进行解耦

当仁不让,第一规则,优先考虑。

2 serivce层的逻辑粒度尽量小,尽量单一

保持service方法的逻辑简洁性,往往一个方法处理逻辑过多会很容易造成代码混乱,并且不容易维护。

3 在小粒度的方法前提下,控制业务逻辑进行上浮

如果是非事物,可以考虑吧逻辑代码上浮到controller,由controller进行组合调用service接口。

如果是事物业务,必须把代码逻辑放在service层,但也需要保持每个方法的小粒度,再由一个方法来进行业务逻辑层控制,并暴露给contrller使用。

当然非业务的事物情况下,也可以把部分contrller里面共同的逻辑,下潜到service实现。(具体根据service具体业务属性进行划分)

但同上,每个子方法都应该具有小粒度和单一的特性。

为什么要这样做?

在上面提到,当第一次操作db后,如果方法一直没执行完并退出,会一直占用链接。这段时间链接是无法被其他人使用的,哪怕链接处于空闲状态。

这样的结果就是100个复杂的业务来了,service层使用了100个数据链进行长时间处理(连接池只提供100个链接),这时其他一个执行查询的小业务请求来了,由于链接全部被占用了,这时这地101个请求就无法处理,只有等。

如果service足够简单,让controller来控制部分业务逻辑(由一个一个小粒度的service方法组成),

A 调用一个service方法结束后会先把链接释放出来;

B 这时其他业务请求才有可能获取到链接,并进行处理,小请求处理完后会释放链接;(能很快的做出相应)

C 之前的contrller继续调用serivce方法,绑定到释放的链接,继续处理。(响应速度延迟不大)

这样100个链接能支持100个以上的请求业务,才能【实现高并发】。否则100个链接提供的并发支持非常有限。

关键思路:

1 调用小粒度service方法,让使用完后,及时释放,尽量避免不用但一直占用资源的时间段产生

2 让使用db资源的时间片尽可能的小,处理过程中可以让其他需要资源的业务请求也能够参与进来 。原创微信公众号:卧龙会IT技术。

3 让想用资源的能及时用到资源,占用资源但空闲状态的释放资源,【最大化】利用有限的资源。

以上是大多数情况下的处理方式,但不能一篇而论。需要根据功能模块和业务场景选择性的使用。

---好东西就要分享给你朋友圈---

  • 发表于:
  • 原文链接:http://kuaibao.qq.com/s/20180119A02Q5E00?refer=cp_1026

相关快讯

扫码关注云+社区