1. 程式人生 > >JPA數據懶加載LAZY配合事務@Transactional使用(三)

JPA數據懶加載LAZY配合事務@Transactional使用(三)

select 會話 pre gpo blank 生命周期 string sca 通用

上篇博文《JPA數據懶加載LAZY和實時加載EAGER(二)》講到,如果使用懶加載來調用關聯數據,必須要保證主查詢session(數據庫連接會話)的生命周期沒有結束,否則,你是無法抽取到數據的。那麽如果保證自己想要獲取關聯數據時,數據庫會話session還存在呢?今天講解一種方法,借助Spring提供的@Transactional註解來實現方法內部的操作在同一次數據庫連接中執行。需要註意的是,使用@Transactional註解,必須要保證方法通過Spring組件解析方式處理,spring代理會為方法註入事務攔截邏輯。

關於spring的事務實現原理,可以參考《Spring @Transactional工作原理

一、為實體類ProcessBlock和Node添加一對多的關聯關系。Set<Node>屬性使用懶加載方式。下面給出代碼。  

@Entity(name = "nbpm_processblock")
@NamedQuery(name = "ProcessBlock.findByName", query = "select p from nbpm_processblock p where p.name=?1")
public class ProcessBlock implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy 
= GenerationType.IDENTITY) @Column(name = "id") long id; @Column(name = "name") String name; @Column(name = "description") String description; String subClass; @OneToMany(mappedBy = "processblock", cascade = CascadeType.ALL,fetch=FetchType.LAZY) // @JoinColumn(name="processblock_id")
Set<Node> nodeSet = new HashSet<Node>();

 二、為查詢方法添加事務註解

    @Transactional
    @RequestMapping(value = "/list", method = RequestMethod.GET)
    public String list(ModelMap model,HttpSession session) {
        //ProcessBlockRepository processBlock = ApplicationContextUtil.instance.getBean(ProcessBlockRepository.class);
        //List<ProcessBlock> list = processBlock.findByName1("主幹流程");
        Map<String, Object> params = new HashMap<>();
        params.put("name", "主幹流程");
        List<ProcessBlock> list = ApplicationContextUtil.instance.getJpaUtil().list(
                "select u from simm.spring.entity.ProcessBlock u where u.name=:name", params, ProcessBlock.class);
        System.out.println("準備獲取懶加載數據");
        Set<Node> nodes = list.get(0).getNodeSet();

 三、調試一下,查看調用情況

  1、測試代碼先執行List<ProcessBlock>查詢,之後輸出"準備獲取懶加載數據",最後查詢第一條ProcessBlock對應的節點集合。通過執行日誌很容易看出,懶加載的數據只有在後續的代碼邏輯中被調用後,才會生成sql查詢,在數據庫中執行獲取數據。

  技術分享圖片

  2、先獲取List<ProcessBlock>列表後,在來獲取第一個ProcessBlock對象對應的節點集合。調試顯示已經成功獲取到數據。

   技術分享圖片

  至此,測試完畢。用法很簡單,但是關於spring事務的實現這塊還是很有意思的,一次數據庫連接在線程中通過ThreadLocal變量傳遞,其生命周期靠事務攔截器來控制。這個過程在ORM框架中應該是一種比較通用的思路,在Hibernate中如此,其他框架應該也是相差無幾。感謝你的閱讀,歡迎留言討論交流!

JPA數據懶加載LAZY配合事務@Transactional使用(三)