現在springboot的火熱程度已經超過了spring了,因為springboot簡單快速方便,springboot的初衷就是為了簡化spring的配置,是的開發中集成新功能時更快,簡化或者減少相關的配置。springboot的基礎是“約定大於配置”。整合了所有的框架,可以把springboot當 ...
現在springboot的火熱程度已經超過了spring了,因為springboot簡單快速方便,springboot的初衷就是為了簡化spring的配置,是的開發中集成新功能時更快,簡化或者減少相關的配置。springboot的基礎是“約定大於配置”。整合了所有的框架,可以把springboot當作一個框架集合。
我們來看看spring官網對springboot的特點的描述:
1. 創建獨立的Spring應用程式
2.直接嵌入Tomcat、Jetty或Undertow(不需要部署WAR文件)
3.提供自以為是的“starter”依賴項以簡化構建配置
4.儘可能自動配置Spring和第三方庫
5.提供生產就緒功能,如度量、運行狀況檢查和外部化配置
6.完全沒有代碼生成,也不需要XML配置(重點)
今天來介紹下springboot整合mybatis。
一.springboot項目的搭建
1.springboot項目的創建
2.springboot跳轉頁面,這裡跟spring是差不多的。
@RestController public class HelloController { @RequestMapping(value = "/hello") public String hello(){ return "index"; } } 這裡的返回的"index"預設位於resources/static下的。
當springboot啟動的時候,我們可以看到這兩行: Tomcat initialized with port(s): 8080 (http) 這一行說明springboot的預設埠為8080。
也可以在application.propertices(application.yml)裡面配置: server: port:8088 Starting Servlet engine: [Apache Tomcat/9.0.31] 這一行說明springboot內置的tomcat的版本。
這樣啟動springboot項目後,在瀏覽器地址欄上輸入localhost:8080/hello。就可以打開一個頁面。
二.springboot整合mybatis
本文不使用application.properties文件 而使用更加簡潔的application.yml文件。將resource文件夾下原有的application.properties文件刪除,創建application.yml配置文件(備註:其實SpringBoot底層會把application.yml文件解析為application.properties),
.yml和.properties沒什麼區別,差異在於yml會有層級的劃分,並且註意在冒號:後面要有空格.
在這裡是使用的@MapperScan註解來,而不是用的mybatisConfig.xml配置mybatis的。
1.配置數據源,在application.yml的配置文件中。
spring: datasource: driver-class-class: com.mysql.jdbc.Driver ## type: com.zaxxer.hikari.HikariDataSource jdbcUrl: jdbc:mysql://localhost:3306/zj?serverTimezone=GMT%2B8 username: root password: root
2.配置mybaits的mapper路徑
mybatis: mapper-locations: classpath:mapping/*.xml
3.mapper介面
public interface UserMapper { /*** * 根據主鍵id查詢用戶 * @param id * @return */ User selectByPrimaryKey(Integer id); }
4.user的實體這裡就不說了,這個很容易
5.在resources下麵創建一個mapping/UserMapper.xml文件,這裡的路徑是對應上面第二部配置的mybatis的mapper路徑的。mapper.xml的namespace就是mapper類的全類名。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cn.seven.demo.dao.UserMapper"> <resultMap id="baseResultMap" type="cn.seven.demo.entity.User"> <id column="id" jdbcType="INTEGER" property="id"></id> <result column="realName" jdbcType="VARCHAR" property="realName"></result> <result column="username" jdbcType="VARCHAR" property="username"></result> <result column="sex" jdbcType="INTEGER" property="sex"></result> </resultMap> <!--根據主鍵查詢值--> <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="baseResultMap"> select * from T_USER where id = #{id} </select> </mapper>
6.mybatis的測試類
@SpringBootTest(classes = SpringbootdemoApplication.class) @RunWith(SpringRunner.class)//讓測試運行於Spring測試環境 public class MybatisTest { @Resource private UserMapper userMapper; @Test public void test(){ User user = userMapper.selectByPrimaryKey(1); System.out.println(user); } }
到這裡springboot整合mybatis就完成了。就是這麼簡單。
三.配置mybatis多數據源
1. 配置MySQL多數據源
spring: datasource: master: driver-class-class: com.mysql.jdbc.Driver type: com.zaxxer.hikari.HikariDataSource jdbcUrl: jdbc:mysql://localhost:3306/zj?serverTimezone=GMT%2B8 username: root password: root slave: driver-class-class: com.mysql.jdbc.Driver type: com.zaxxer.hikari.HikariDataSource jdbcUrl: jdbc:mysql://localhost:3307/zj?serverTimezone=GMT%2B8 username: root password: root
2.由於是多數據源,所以在pringboot都啟動類(*Application.java)上需要禁用預設得數據源組件
//禁用預設的數據源組件 @SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
3.需要自己創建一個動態數據源的組件,這裡我創建的是mybatisConfig.java類;
@Configuration @MapperScan(basePackages = "cn.seven.demo.dao")//掃瞄DAO的包 @Slf4j public class MybatisConfig { /** * 創建主數據源 * @return */ @Bean("master") @Primary //設置優先順序 @ConfigurationProperties("spring.datasource.master") //配置屬性文件 public DataSource master(){ return DataSourceBuilder.create().build();//builder建造者模式 } /** * 創建從數據源 * @return */ @Bean("slave") @Primary @ConfigurationProperties("spring.datasource.slave") public DataSource slave(){ return DataSourceBuilder.create().build(); } /** * 生成自定義的數據源 * @return */ @Bean("dynamicDataSource") public DataSource dynamicDataSource(){ DynamicDataSource dynamicDataSource = new DynamicDataSource(); Map<Object,Object> mapDataSource = new HashMap<Object,Object>(2); mapDataSource.put("master",master()); mapDataSource.put("slave",slave()); //將master數據源作為指定的數據源 dynamicDataSource.setDefaultDataSource(master()); //將master和slave數據源作為指定的數據源 dynamicDataSource.setDataSource(mapDataSource); return dynamicDataSource; } @Bean public SqlSessionFactoryBean sqlSessionFactoryBean() throws IOException { SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean(); //配置數據源,此處配置為關鍵配置,如果沒有將dynamicDataSource作為數據源則不能實現切換 sessionFactoryBean.setDataSource(dynamicDataSource()); //掃描model-entity的包 sessionFactoryBean.setTypeAliasesPackage("cn.seven.demo.entity"); //掃描映射文件 PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver = new PathMatchingResourcePatternResolver(); sessionFactoryBean.setMapperLocations(pathMatchingResourcePatternResolver.getResources("classpath:mapping/*.xml")); return sessionFactoryBean; } /** * 配置事務管理,使用事務時哎方法頭部添加@Transactional註解即可 * @return */ @Bean public PlatformTransactionManager transactionManager(){ return new DataSourceTransactionManager(dynamicDataSource()); } }
4.數據源的註解介面
@Target({ElementType.METHOD,ElementType.TYPE,ElementType.PARAMETER})//設置註解的作用範圍 @Retention(RetentionPolicy.RUNTIME) @Documented public @interface DataSource { String value() default "master"; }
5.自定義的動態數據源
public class DynamicDataSource extends AbstractRoutingDataSource { /** * 如果不希望數據源在啟動配置時就載入好,可以定製這個方法,從任何你希望的地方讀取並返回數據源, * 比如從資料庫,文件,外部介面等讀取數據源信息,並最終返回一個DataSource實現類對象即可 * @return */ @Override protected DataSource determineTargetDataSource() { return super.determineTargetDataSource(); } /** * 如果希望所有的數據源在啟動配置時載入好,這裡通過設置數據源key值來切換數據源,定製這個方法 * @return */ @Override protected Object determineCurrentLookupKey() { return DynamicDataSourceContextHolder.getDataSourceKey(); } /** * 設置預設的數據源 * @param defaultDataSource */ public void setDefaultDataSource(Object defaultDataSource){ super.setDefaultTargetDataSource(defaultDataSource); } /** * 社渚數據源 * @param dataSource */ public void setDataSource(Map<Object,Object> dataSource){ super.setTargetDataSources(dataSource); //將數據源的key放到數據源上下文的key集合中,用於切換時判斷數據源是否有效 DynamicDataSourceContextHolder.addDataSourceKey(dataSource.keySet()); } }
6.動態數據源上下文
public class DynamicDataSourceContextHolder { /** * 用於存放數據源的本地線程 */ private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>(){ /** * 講master數據源的key作為預設的數據源的key * @return */ @Override protected String initialValue() { // return super.initialValue();// return "master"; } }; /**數據源的key集合,用於切換時判斷數據源是否存在*/ private static List<Object> dataSourceKey = new ArrayList<Object>(); /** * @return the value of contextHolder */ public static ThreadLocal<String> getContextHolder() { return contextHolder; } /** * @return the value of dataSourceKey */ public static List<Object> getDataSourceKey() { return dataSourceKey; } /** * Sets the dataSourceKey * * @param dataSourceKey dataSourceKey */ public static void setDataSourceKey(String dataSourceKey) { contextHolder.set(dataSourceKey); } /** * 重置數據源 */ public static void cleanDataSource(){ contextHolder.remove(); } /** * 判斷是否包含數據源 * @param key 數據源的key * @return yes no */ public static boolean containDataSourceKey(String key){ return dataSourceKey.contains(key); } /** * 添加數據源key,支持加多個,所以需要用collection * @param keys 數據源key * @return */ public static boolean addDataSourceKey(Collection<? extends Object> keys){ return dataSourceKey.add(keys); } }
7. 動態數據源的切麵類
@Aspect @Order(-1) //優先於事務註解執行 @Component @Slf4j public class DynamicDataSourceAspect { @Before("@annotation(dataSource)") public void switchDataSource(JoinPoint point,DataSource dataSource){ if(!DynamicDataSourceContextHolder.containDataSourceKey(dataSource.value())){ System.out.println("資料庫不匹配 : "+ dataSource.value()); }else{ System.out.println("資料庫切換 : "+ dataSource.value()); DynamicDataSourceContextHolder.setDataSourceKey(dataSource.value()); } } /** * 清空數據源 * @param point * @param dataSource */ @After("@annotation(dataSource)") public void restoreDataSource(JoinPoint point,DataSource dataSource){ DynamicDataSourceContextHolder.cleanDataSource(); System.out.println("資料庫連接清空:"+dataSource.value()); } }
8.註意mapper介面的userMapper的查詢方法上設置:@DataSource("slave"),由於我們的預設資料庫是master,所以這裡需要設置成slave;
/*** * 配置多數據源 註解後面的表示方法 * @param id * @return */ @DataSource("slave") User selectByPrimaryKey(Integer id);
同時由於在mybaitsConfig里寫了掃描映射文件的代碼: //掃描映射文件 PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver = new PathMatchingResourcePatternResolver(); sessionFactoryBean.setMapperLocations(pathMatchingResourcePatternResolver.getResources("classpath:mapping/*.xml")); 所以需要將之前在yml文件里設置的讀取mapper.xml文件的路徑刪除。
9.使用上面的測試類測試
到這,springboot整合mybatis並設置多數據源就已經完成了。
歡迎大家下載源碼:https://files.cnblogs.com/files/pluto-charon/springbootdemo.rar