文章目录

  • 前言
  • pom
  • yml配置
  • 整合方式
  • 1. 依赖直接注入
  • 2. 通过ApplicationContext创建Session
  • 难点

前言

自由探索SpringBoot整合Hibernate 4.x,本来觉得是个轻松加愉快的事,没想到因为Bean注入的问题卡了挺久。。。以下具体内容。

pom

首先是pom文件,这边我的SpringBoot版本比较新,用的2.5.3:

spring boot整合thymeleaf spring boot整合hibernate_List


其次是javax.persistence包,以及hibernate-entitymanager包:

spring boot整合thymeleaf spring boot整合hibernate_List_02


其他的加个lombok和数据库connector就OK,可以开始愉快的整合了:

spring boot整合thymeleaf spring boot整合hibernate_spring_03

yml配置

这里主要是配置数据库,其他的一律用默认,毕竟只需要做到整合后能用即可:

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/Grocery
    username: root
    password: 12345678
    driver-class-name: com.mysql.cj.jdbc.Driver

整合方式

1. 依赖直接注入

首先,写个简单的BaseDao:

package com.example.localtests.dao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;

@Repository
public class BaseDao {
    protected EntityManagerFactory factory;
    protected EntityManager manager;

    @Autowired
    protected void setFactory(EntityManagerFactory factory){
        this.factory = factory;
        this.manager = factory.createEntityManager();
    }
}

这里用的是set方法注入,各位童鞋可以自己选用喜欢的注入方式哈。
然后下面写具体的Dao,这里就直接开始具体查数据:

package com.example.localtests.dao;

import org.springframework.stereotype.Repository;

import javax.persistence.Query;
import java.util.List;

@Repository
public class LocalTestDao extends BaseDao {

    public List getResult() {
        String sql = "select * from t_ce_port";
        Query query = manager.createNativeQuery(sql);
        return query.getResultList();
    }
}

写了个最简单的SQL来测试。
然后写Service以及Controller,都是最快捷的:
Service:

package com.example.localtests.service;

import com.example.localtests.dao.LocalTestDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class LocalService {
    private LocalTestDao dao;

    @Autowired
    private void setDao(LocalTestDao dao){
        this.dao = dao;
    }

    public List getLocalResult(){
        return dao.getResult();
    }
}

Controller:

package com.example.localtests.controller;

import com.example.localtests.service.LocalService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class LocalController {
    private LocalService service;

    @Autowired
    private void setService(LocalService service){
        this.service = service;
    }

    @GetMapping(path = "/local")
    public List getLocalData(){
        return service.getLocalResult();
    }
}

好了,写完以上就已经可以愉快的测试了,启动项目—然后报错,报错如图:

spring boot整合thymeleaf spring boot整合hibernate_java_04


明明都已经添加了为什么还会Bean Not Found呢,由于是SpringBoot方式整合,不存在XML写Bean的方式,处理起来很简单,在pom里边加上springBoot对jpa的支持就好了:

spring boot整合thymeleaf spring boot整合hibernate_spring_05


非常简单,再次启动,一切正常:

spring boot整合thymeleaf spring boot整合hibernate_spring_06


输入http://localhost:8080/local查询,可以看到返回数据:

spring boot整合thymeleaf spring boot整合hibernate_List_07

2. 通过ApplicationContext创建Session

思路是拿到ApplicationContext,然后再通过getBean()方法拿到SessionFactory,最后创建Session,第一步写个util:

package com.example.localtests.utils;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import javax.persistence.EntityManagerFactory;

@Component
public class ApplicationContextUtils implements ApplicationContextAware {

    private static ApplicationContext context;

    @Override
    public void setApplicationContext(@NotNull ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }

    public static ApplicationContext getContext() {
        return context;
    }

    public static Session getSession(){
        return context.getBean(SessionFactory.class).openSession();
    }

}

以上,继承ApplicationContextAware的标准写法,写一步在Dao中使用Session对象:

public List getResultFromContext(){
        String sql = "select * from t_ce_port where audit_state = 'identification'";
        Query query = ApplicationContextUtils.getSession().createNativeQuery(sql);
        return query.getResultList();
    }

然后调用getResultFromContext()方法输出结果就ok:

@GetMapping(path = "/localContext")
    public List getContextData(){
        return service.getContextResult();
    }

最后,启动项目访问/localContext接口,查看数据:

spring boot整合thymeleaf spring boot整合hibernate_List_08

没有问题,完结。

难点

回过头来看其实不是很难,但主要会碰到很奇怪的坑。
DAO层中注入的EntityManager报npe,即注入的内容为空值,这个其实跟找不到EntityManagerFactory这个Bean是同一种问题,即没有把Bean注入容器,启动项目扫描组件的时候,就会因为扫描不到Bean报错。
在Spring时期,可以通过配置xml的方式来写入,但在SpringBoot项目里,还是建议用注解形式去写注入。