Mybatis 配置
Mybatis 配置文件
MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录
mybatis官方中文文档
http://www.mybatis.org/mybatis-3/zh/
引入Mybatis
预准备
创建一个maven的webapp项目, 参考web项目配置
1 . 首先引入mybatis的jar包, 以及mybatis-spring的整合包 .
2 . 引入spring的jar包依赖
修改pom.xml
文件 , 添加下面的依赖 :
<properties>
<spring.version>4.3.4.RELEASE</spring.version>
<mybatis.version>3.4.0</mybatis.version>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.0-b02</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!-- spring核心包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- mybatis核心包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<!-- mapper/spring包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<!-- mybatis分页插件依赖 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.0.0</version>
</dependency>
<!-- 导入Mysql数据库链接jar包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.30</version>
</dependency>
<!-- 阿里数据库数据源 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.7</version>
</dependency>
<!--JSON 解析-->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.0</version>
</dependency>
<!--时间插件-->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
</dependencies>
3 . 创建mybatis-config.xml
文件 , 这个文件主要是存放一些针对于全局的配置 .
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mapper.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!--开启驼峰命名法 Table(create_time) -> Entity(createTime)-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<!-- 这个是我本地的实体类的alias , 可以全局使用 -->
<typeAliases>
<typeAlias alias="User" type="com.lemy.spring_mybatis.pojo.UserDo"/>
</typeAliases>
<!-- 分页插件 : 插件文档地址 : https://github.com/pagehelper/Mybatis-PageHelper/blob/master/README_zh.md -->
<plugins>
<!-- com.github.pagehelper为PageHelper类所在包名 -->
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!-- 使用下面的方式配置参数 -->
<property name="helperDialect" value="mysql"/>
<property name="reasonable" value="true"/>
<property name="supportMethodsArguments" value="true"/>
</plugin>
</plugins>
</configuration>
4 . 配置mybatis的数据源以及相关配置
在 resources
文件夹下面创建spring
文件夹 ,在 spring
文件夹中创建 datasource.xml
, 用于配置数据源
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 扫描service -->
<context:component-scan base-package="com.lemy.spring_mybatis.service" />
<!-- 1:引入配置文件 -->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="location" value="classpath:jdbc.properties" />
</bean>
<!-- 2 . 配置数据源 -->
<bean id="stat-filter" class="com.alibaba.druid.filter.stat.StatFilter">
<property name="slowSqlMillis" value="800" />
<property name="logSlowSql" value="true" />
</bean>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="filters" value="stat" />
<property name="proxyFilters">
<list>
<ref bean="stat-filter" />
</list>
</property>
<property name="initialSize" value="5" />
<property name="minIdle" value="5" />
<property name="maxActive" value="200" />
<property name="maxWait" value="60000" />
<property name="timeBetweenEvictionRunsMillis" value="3000" />
<property name="minEvictableIdleTimeMillis" value="300000" />
<property name="validationQuery" value="show status like \'%Service_Status%\';" />
<property name="testWhileIdle" value="true" />
<property name="testOnBorrow" value="false" />
<property name="testOnReturn" value="false" />
<!-- 打开removeAbandoned功能 -->
<property name="removeAbandoned" value="true" />
<!-- 600秒,也就是10分钟 -->
<property name="removeAbandonedTimeout" value="600" />
<!-- 关闭abanded连接时输出错误日志 -->
<property name="logAbandoned" value="true" />
</bean>
<!-- 3: 配置sqlSessionFactory对象 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- 加载全局配置 -->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<!-- 加载存放sql的xml文件 , 此处可以使用正则匹配文件 , 因为我只有一个文件 , 所以直接写上这个文件的名字 -->
<property name="mapperLocations" value="classpath*:mybatis/t_user.xml"/>
</bean>
<!-- 4:配置扫描mapper层接口, 动态实现mapper层接口 , 注入spring容器 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--
配置需要扫描的DAO的包,
com.lemy.spring_mybatis.mapper 是存放mapper文件的路径
-->
<property name="basePackage" value="com.lemy.spring_mybatis.mapper" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
<!-- 5: 事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 使用全注释事务 -->
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
在 resources
根目录下面 创建 jdbc.properties
配置文件存放mysql的链接配置
jdbc.url = jdbc:mysql://121.41.170.231:30005/saas_dev?useUnicode=true&characterEncoding=utf8
jdbc.username = root
jdbc.password = 2015wjb
5 . 在 resources
下面创建 mybatis
文件夹用于存放sql配置文件 , 然后在 mybatis
文件夹中创建 t_user.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mapper.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lemy.spring_mybatis.mapper.UserMapper">
<resultMap id="UserResult" type="User">
<result column="id" property="id" jdbcType="INTEGER"/>
<result column="userName" property="userName" jdbcType="VARCHAR"/>
<result column="password" property="password" jdbcType="VARCHAR"/>
<result column="mobile" property="mobile" jdbcType="VARCHAR"/>
<result column="tel" property="tel" jdbcType="VARCHAR"/>
<result column="email" property="email" jdbcType="VARCHAR"/>
</resultMap>
<sql id="_userDoColumn">
u.id, u.userName, u.password, u.mobile, u.tel, u.email
</sql>
<select id="queryUserById" parameterType="java.lang.Long" resultMap="UserResult">
SELECT <include refid="_userDoColumn"/>
FROM t_user u
where u.id = #{userId}
</select>
<!--查询全公司成员-->
<select id="queryUserListByCompanyId" parameterType="java.util.HashMap" resultMap="UserResult">
SELECT
<include refid="_userDoColumn"/>
FROM
t_user u
WHERE u.company_id = #{companyId}
</select>
</mapper>
配置好了之后 , 创建java的Mapper代码 , Mybatis提供了一种可以只创建interface的类就可以映射到xml的功能 , 所以我们只需要创建 UserMapper.java
的interface . 如下图 :
Spring + Mybatis 代码整合
6 . 在 src/main/java
文件夹中创建我们的java代码的目录结构 . 如下图所示 :
创建service
和 pojo
文件夹 , 分别存放业务层和实体类 . 详细目录如下图所示 :
创建UserService.java
代码如下 :
package com.lemy.spring_mybatis.service;
import com.lemy.spring_mybatis.pojo.UserDo;
import java.util.List;
/**
* @author leiniao
*/
public interface UserService {
UserDo queryUserById(Long userId);
List<UserDo> queryUserListByCompanyId(Long companyId);
}
创建 UserDo.java
实体类 , 代码如下 :
package com.lemy.spring_mybatis.pojo;
public class UserDo {
private Integer id;
private String userName;
private String password;
private String mobile;
private String tel;
private String email;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "UserDo{" +
"id=" + id +
", userName='" + userName + '\'' +
", password='" + password + '\'' +
", mobile='" + mobile + '\'' +
", tel='" + tel + '\'' +
", email='" + email + '\'' +
'}';
}
}
7 . 创建好了目录结构之后 , 再配置spring . 在 src/main/resources/spring
目录下面创建 applicationContext.xml
. 如下图 :
配置代码如下 :
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 扫描 controller -->
<context:component-scan base-package="com.lemy.spring_mybatis.controller" />
<mvc:annotation-driven>
<!-- 消息转换器 -->
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
</beans>
8 . 配置 web.xml
文件
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>spring-mybatis-demo</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:spring/datasource.xml
</param-value>
</context-param>
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>spring-mybatis-servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring-mybatis-servlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
9 . spring MVC 采用RestFul风格的API模式 .
创建UserController
, 如下图 :
代码如下 :
package com.lemy.spring_mybatis.controller;
import com.google.gson.Gson;
import com.lemy.spring_mybatis.pojo.UserDo;
import com.lemy.spring_mybatis.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
/**
* @author leiniao
*/
@RestController
public class UserController {
@Autowired
private UserService userService;
private Gson gson = new Gson();
@RequestMapping(value = "/user/{userId}", method = RequestMethod.GET)
@ResponseBody
public String getUser(@PathVariable("userId") Long userId) {
UserDo userDo = userService.queryUserById(userId);
return gson.toJson(userDo);
}
@RequestMapping(value = "/user/{userId}", method = RequestMethod.PATCH)
public @ResponseBody List<UserDo> getListByCompanyId(@PathVariable("userId") Long userId, @RequestBody HashMap<String, String> map) {
System.out.println(userId);
System.out.println(map);
Long companyId = Long.valueOf(map.get("companyId"));
List<UserDo> userList = userService.queryUserListByCompanyId(companyId);
return userList;
}
}
10 . 至此 , Spring + Mybatis的整合就完成了. 可以使用Postman插件去测试你的RestFul的API了 .
Mybatis多数据源的配置(基于AOP配置)
1、创建DynamicDataSource
类
创建 `DynamicDataSource` 类 , 继承AbstractDataSource类 , 这个是Spring的抽象类 .
改类充当了DataSource的路由中介, 能在运行时, 根据某种key值来动态切换到真正的DataSource上。这个是我们配置多数据源的关键 .
package com.lemy.spring_mybatis.multiple;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* 动态分配数据库源
*
* @author leiniao
*/
public class DynamicDatasource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceTypeManager.get();
}
}
2、创建数据源管理类 DataSourceTypeManager
这个类是用于动态设置数据源的类 .
package com.lemy.spring_mybatis.multiple;
/**
* 数据库源类型管理
*
* @author leiniao
*/
public class DataSourceTypeManager {
private static final ThreadLocal<String> dataSourceTypes = new ThreadLocal<String>(){
@Override
protected String initialValue() {
return DataSourceType.MASTER;
}
};
public static String get(){
return dataSourceTypes.get();
}
public static void set(String dataSourceType){
dataSourceTypes.set(dataSourceType);
}
public static void reset(){
dataSourceTypes.set(DataSourceType.MASTER);
}
}
3、创建数据源类型的常量类 DataSourceType
这个类就是一个存放数据源类型的常量类
package com.lemy.spring_mybatis.multiple;
/**
* 数据源类型
*
* @author leiniao
*/
public class DataSourceType {
//主库
public static final String MASTER = "master";
//从库
public static final String SLAVE = "slave";
}
4、多数据源的配置文件
创建 multiple-datasource.xml , 具体配置如下 :
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.lemy.spring_mybatis.service"/>
<context:component-scan base-package="com.lemy.spring_mybatis.multiple"/>
<!-- 1:引入配置文件 -->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="location" value="classpath:jdbc.properties"/>
</bean>
<bean id="dataSourceMaster" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close" init-method="init">
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<bean id="dataSourceSlave" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close" init-method="init">
<property name="url" value="${jdbc.url2}"/>
<property name="username" value="${jdbc.username2}"/>
<property name="password" value="${jdbc.password2}"/>
</bean>
<bean id="dataSource" class="com.lemy.spring_mybatis.multiple.DynamicDatasource">
<property name="defaultTargetDataSource" ref="dataSourceMaster"/>
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry key="master" value-ref="dataSourceMaster"/>
<entry key="slave" value-ref="dataSourceSlave"/>
</map>
</property>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="mapperLocations" value="classpath:mybatis/*.xml"/>
</bean>
<aop:aspectj-autoproxy/>
<!-- Transaction manager for a single JDBC DataSource -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 使用annotation定义事务 -->
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" order="2"/>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.lemy.spring_mybatis.mapper"/>
<!-- 因为sqlSessionFactoryBeanName是动态的 , 因此此处不用配置 -->
<!-- <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> -->
</bean>
</beans>
5、创建AOP的管理类
创建 DataSourceInterceptor.java
内容如下 :
package com.lemy.spring_mybatis.multiple;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
/**
* 基本注解的AOP动态切换数据源
*
* @author leiniao
*/
@Aspect
@Component // 提供spring auto inject bean
@Order(0) // 请注意:这里order一定要小于tx:annotation-driven的order,即先执行DataSourceInterceptor切面,再执行事务切面,才能获取到最终的数据源
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class DataSourceInterceptor {
Logger logger = LoggerFactory.getLogger(DataSourceInterceptor.class);
@Pointcut("execution(* com.lemy.spring_mybatis.mapper.TagsMapper.*(..))")
public void dataSourceSlave(){
//do nothing...
logger.info("use slave datasource");
}
@Before("dataSourceSlave()")
public void beforeSlave(JoinPoint jp) {
DataSourceTypeManager.set(DataSourceType.SLAVE);
}
@Pointcut("execution(* com.lemy.spring_mybatis.mapper.UserMapper.*(..))")
public void dataSourceMaster(){
//do nothing...
logger.info("use master datasource");
}
@Before("dataSourceMaster()")
public void beforeMaster(JoinPoint jp) {
DataSourceTypeManager.set(DataSourceType.MASTER);
}
}
至此 , 多数据源的配置就算是完成了 .
PS : Spring AOP的具体用法 , 这里不再说明 . 也不是本文的重点 ,大家可以自己学习AOP的用法 .