后端开发 \ SpringBoot \ SpringBoot学习-(六)SpringBoot与Mybatis整合

SpringBoot学习-(六)SpringBoot与Mybatis整合

总点击76
简介:mybatis-spring-boot-starter依赖树如下: mybatis开发团队为SpringBoot提供了MyBatis-Spring-Boot-Starter。

mybatis-spring-boot-starter依赖树如下:

SpringBoot学习-(六)SpringBoot与Mybatis整合

mybatis开发团队为Spring Boot 提供了 MyBatis-Spring-Boot-Starter


首先,MyBatis-Spring-Boot-Starter will:

Autodetect an existing DataSource.

Will create and register an instance of a SqlSessionFactoryBean passing that DataSource as an input.

Will create and register an instance of a SqlSessionTemplate got out of the SqlSessionFactoryBean.

Autoscan your mappers,link them to the SqlSessionTemplate and register them to Spring context so they can be injected into your beans.

来源: http://www.mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/index.html

百度翻译过来如下:

自动检测现有的数据源。

将创建并登记一sqlsessionfactorybean传递数据源作为输入的一个实例。

将创建一个实例并登记sqlsessiontemplate了sqlsessionfactorybean。

自动扫描你的映射,它们链接到sqlsessiontemplate和登记他们的Spring上下文可以注入你的bean。

就是说,使用了该Starter之后,只需要定义一个DataSource即可,它会自动创建使用该DataSource的SqlSessionFactoryBean以及SqlSessionTemplate。会自动扫描你的Mappers,连接到SqlSessionTemplate,并注册到Spring上下文中。

1.添加pom依赖

<!-- spring mvc支持 -->

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</dependency>

<!-- springboot整合mybatis(核心就这一个) -->

<dependency>

<groupId>org.mybatis.spring.boot</groupId>

<artifactId>mybatis-spring-boot-starter</artifactId>

<version>1.3.1</version>

</dependency>

<!-- 阿里巴巴druid数据库连接池 -->

<dependency>

<groupId>com.alibaba</groupId>

<artifactId>druid</artifactId>

<version>1.1.3</version>

</dependency>

<!-- mysql驱动 -->

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

</dependency>

2.配置datasource(Druid)

具体配置步骤点这里

3.配置application.yml

mybatis:

# mybatis配置文件

config-location: classpath:mybatis.xml

# 映射文件所在路径

mapper-locations:

# 前面的 - 不要删除

- classpath:mapper/*.xml

项目目录结构如下:

SpringBoot学习-(六)SpringBoot与Mybatis整合

4.代码(没有任何变化,可以跳过去)

mybatis配置

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"

"http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>

<settings>

<!-- 打印sql语句 -->

<setting name="logImpl" value="STDOUT_LOGGING" />

</settings>

</configuration>

实体类

package com.ahut.entity;

import java.io.Serializable;

import java.util.Date;

/**

*

* @ClassName: GoodsType

* @Description: 商品类型实体类

* @author cheng

* @date 2017年7月12日 下午5:37:33

*/

public class GoodsType implements Serializable {

private static final long serialVersionUID = -4039634130866820668L;

private String typeId;// 类型id

private String typeName;// 类型名称

private Date createTime;// 创建时间

private Date updateTime;// 更新时间

/**

* 重写tostring

*/

@Override

public String toString() {

return "GoodsType [typeId=" + typeId + ",typeName=" + typeName + ",createTime=" + createTime + ",updateTime="

+ updateTime + "]";

}

/**

* 无参构造函数

*/

public GoodsType() {

super();

}

/**

* 有参构造函数

*

* @param typeId

* @param typeName

* @param createTime

* @param updateTime

*/

public GoodsType(String typeId,String typeName,Date createTime,Date updateTime) {

super();

this.typeId = typeId;

this.typeName = typeName;

this.createTime = createTime;

this.updateTime = updateTime;

}

public String getTypeId() {

return typeId;

}

public void setTypeId(String typeId) {

this.typeId = typeId;

}

public String getTypeName() {

return typeName;

}

public void setTypeName(String typeName) {

this.typeName = typeName;

}

public Date getCreateTime() {

return createTime;

}

public void setCreateTime(Date createTime) {

this.createTime = createTime;

}

public Date getUpdateTime() {

return updateTime;

}

public void setUpdateTime(Date updateTime) {

this.updateTime = updateTime;

}

}

映射文件

<?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="com.ahut.mapper.GoodsTypeMapper">

<resultMap id="BaseResultMap" type="com.ahut.entity.GoodsType">

<id column="TYPE_ID" jdbcType="VARCHAR" property="typeId" />

<result column="TYPE_NAME" jdbcType="VARCHAR" property="typeName" />

<result column="CREATE_TIME" jdbcType="TIMESTAMP" property="createTime" />

<result column="UPDATE_TIME" jdbcType="TIMESTAMP" property="updateTime" />

</resultMap>

<!-- 添加一个商品类型 -->

<insert id="saveGoodsType" parameterType="com.ahut.entity.GoodsType">

insert into goods_type (TYPE_ID,TYPE_NAME,CREATE_TIME)

values (replace(UUID(),'-',''),#{typeName,jdbcType=VARCHAR},NOW())

</insert>

<!-- 删除一个商品类型 -->

<delete id="deleteGoodsType" parameterType="java.lang.String">

delete from goods_type

where TYPE_ID = #{typeId,jdbcType=VARCHAR}

</delete>

<!-- 修改一个商品类型 -->

<update id="updateGoodsType" parameterType="com.ahut.entity.GoodsType">

update goods_type

set TYPE_NAME = #{typeName,

UPDATE_TIME = NOW()

where TYPE_ID = #{typeId,jdbcType=VARCHAR}

</update>

<!-- 获取所有的商品类型 -->

<select id="getList" resultMap="BaseResultMap">

select

<include refid="Base_Column_List" />

from goods_type

order by CREATE_TIME ASC

</select>

<!-- 依据商品名称查询 -->

<select id="getByTypeName" parameterType="java.lang.String"

resultMap="BaseResultMap">

select

<include refid="Base_Column_List" />

from goods_type

where TYPE_NAME = #{typeName,jdbcType=VARCHAR}

</select>

<!-- 自动生成 -->

<sql id="Base_Column_List">

TYPE_ID,CREATE_TIME,UPDATE_TIME

</sql>

<select id="selectByPrimaryKey" parameterType="java.lang.String"

resultMap="BaseResultMap">

select

<include refid="Base_Column_List" />

from goods_type

where TYPE_ID = #{typeId,jdbcType=VARCHAR}

</select>

<delete id="deleteByPrimaryKey" parameterType="java.lang.String">

delete from goods_type

where TYPE_ID = #{typeId,jdbcType=VARCHAR}

</delete>

<insert id="insert" parameterType="com.ahut.entity.GoodsType">

insert into goods_type (TYPE_ID,

UPDATE_TIME)

values (#{typeId,

#{createTime,jdbcType=TIMESTAMP},

#{updateTime,jdbcType=TIMESTAMP})

</insert>

<insert id="insertSelective" parameterType="com.ahut.entity.GoodsType">

insert into goods_type

<trim prefix="(" suffix=")" suffixOverrides=",">

<if test="typeId != null">

TYPE_ID,

</if>

<if test="typeName != null">

TYPE_NAME,

</if>

<if test="createTime != null">

CREATE_TIME,

</if>

<if test="updateTime != null">

UPDATE_TIME,

</if>

</trim>

<trim prefix="values (" suffix=")" suffixOverrides=",">

<if test="typeId != null">

#{typeId,

</if>

<if test="typeName != null">

#{typeName,

</if>

<if test="createTime != null">

#{createTime,

</if>

<if test="updateTime != null">

#{updateTime,

</if>

</trim>

</insert>

<update id="updateByPrimaryKeySelective" parameterType="com.ahut.entity.GoodsType">

update goods_type

<set>

<if test="typeName != null">

TYPE_NAME = #{typeName,

</if>

<if test="createTime != null">

CREATE_TIME = #{createTime,

</if>

<if test="updateTime != null">

UPDATE_TIME = #{updateTime,

</if>

</set>

where TYPE_ID = #{typeId,jdbcType=VARCHAR}

</update>

<update id="updateByPrimaryKey" parameterType="com.ahut.entity.GoodsType">

update goods_type

set TYPE_NAME = #{typeName,

CREATE_TIME = #{createTime,

UPDATE_TIME = #{updateTime,jdbcType=TIMESTAMP}

where TYPE_ID = #{typeId,jdbcType=VARCHAR}

</update>

</mapper>

接口层

package com.ahut.mapper;

import java.util.List;

import com.ahut.entity.GoodsType;

/**

*

* @ClassName: GoodsTypeDao

* @Description: 商品类型数据访问接口

* @author cheng

* @date 2017年7月17日 上午9:45:41

*/

public interface GoodsTypeMapper {

/**

*

* @Title: saveGoodsType

* @Description: 添加一个商品类型

* @param goodsType

* @throws Exception

*/

void saveGoodsType(GoodsType goodsType) throws Exception;

/**

*

* @Title: deleteGoodsType

* @Description: 删除一个商品类型

* @param typeId

* @throws Exception

*/

void deleteGoodsType(String typeId) throws Exception;

/**

*

* @Title: updateGoodsType

* @Description: 修改一个商品类型

* @param goodsType

* @throws Exception

*/

void updateGoodsType(GoodsType goodsType) throws Exception;

/**

*

* @Title: getList

* @Description: 获取所有商品类型列表

* @return

* @throws Exception

*/

List<GoodsType> getList() throws Exception;

/**

*

* @Title: getByTypeName

* @Description: 依据商品名称查询

* @param typeName

* @return

* @throws Exception

*/

GoodsType getByTypeName(String typeName) throws Exception;

}

业务逻辑接口

package com.ahut.service;

import java.util.List;

import com.ahut.entity.GoodsType;

/**

*

* @ClassName: GoodsTypeService

* @Description: 商品类型业务逻辑接口

* @author cheng

* @date 2017年7月17日 上午10:03:28

*/

public interface GoodsTypeService {

/**

*

* @Title: saveGoodsType

* @Description: 添加一个商品类型

* @param goodsType

* @throws Exception

*/

String saveGoodsType(GoodsType goodsType) throws Exception;

/**

*

* @Title: deleteGoodsType

* @Description: 删除一个商品类型

* @param typeId

* @throws Exception

*/

void deleteGoodsType(String typeId) throws Exception;

/**

*

* @Title: updateGoodsType

* @Description: 修改一个商品类型

* @param goodsType

* @throws Exception

*/

String updateGoodsType(GoodsType goodsType) throws Exception;

/**

*

* @Title: getList

* @Description: 从域对象中获取所有商品类型列表

* @return

* @throws Exception

*/

List<GoodsType> getGoodsTypeList() throws Exception;

/**

*

* @Title: getList

* @Description: 从数据库中获取所有商品类型列表

* @return

* @throws Exception

*/

List<GoodsType> getList() throws Exception;

/**

*

* @Title: getByTypeName

* @Description: 依据商品名称查询

* @param typeName

* @return

* @throws Exception

*/

GoodsType getByTypeName(String typeName) throws Exception;

}

业务逻辑实现

package com.ahut.serviceImpl;

import java.util.List;

import javax.servlet.ServletContext;

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

import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional;

import org.springframework.web.context.ContextLoader;

import com.ahut.entity.GoodsType;

import com.ahut.mapper.GoodsTypeMapper;

import com.ahut.service.GoodsTypeService;

/**

*

* @ClassName: GoodsTypeServiceImpl

* @Description: 商品类型业务逻辑处理

* @author cheng

* @date 2017年7月17日 上午10:04:31

*/

@Service

@Transactional(rollbackFor = { RuntimeException.class,Exception.class })

public class GoodsTypeServiceImpl implements GoodsTypeService {

// 数据访问

@Autowired

private GoodsTypeMapper typeDao;

/**

*

* @Title: saveGoodsType

* @Description: 添加一个商品类型

* @param goodsType

* @throws Exception

*/

@Override

public String saveGoodsType(GoodsType goodsType) throws Exception {

// 检查商品类型名称是否重复

if (!checkTypeName(goodsType.getTypeName())) {

// 添加

typeDao.saveGoodsType(goodsType);

// 更新域对象

updateServletContext();

return "添加成功";

} else {

return "商品类型名称已存在,添加失败";

}

}

/**

*

* @Title: deleteGoodsType

* @Description: 删除一个商品类型

* @param typeId

* @throws Exception

*/

@Override

public void deleteGoodsType(String typeId) throws Exception {

// 删除

typeDao.deleteGoodsType(typeId);

// 更新域对象

updateServletContext();

}

/**

*

* @Title: updateGoodsType

* @Description: 修改一个商品类型

* @param goodsType

* @throws Exception

*/

@Override

public String updateGoodsType(GoodsType goodsType) throws Exception {

// 检查商品类型名称是否重复

if (!checkTypeName(goodsType.getTypeName())) {

// 修改

typeDao.updateGoodsType(goodsType);

// 更新域对象

updateServletContext();

return "更新成功";

} else {

return "商品类型名称已存在,更新失败";

}

}

/**

*

* @Title: getGoodsTypeList

* @Description: 从域对象中获取所有商品类型列表

* @return

* @throws Exception

*/

@Override

public List<GoodsType> getGoodsTypeList() throws Exception {

return typeDao.getList();

}

/**

*

* @Title: getList

* @Description: 从数据库中获取所有商品类型列表

* @return

* @throws Exception

*/

public List<GoodsType> getList() throws Exception {

List<GoodsType> typeList = null;

// 获取

typeList = typeDao.getList();

return typeList;

}

/**

*

* @Title: checkTypeName

* @Description: 检查商品类型名称是否重复

* @param typeName

*/

private boolean checkTypeName(String typeName) throws Exception {

// 依据商品名称查询

GoodsType goodsType = typeDao.getByTypeName(typeName);

return goodsType == null ? false : true;

}

/**

*

* @Title: updateServletContext

* @Description: 更新域对象里的内容

* @throws Exception

*/

private void updateServletContext() throws Exception {

// 通过Spring获取ServletContext域对象

ServletContext servletContext = ContextLoader.getCurrentWebApplicationContext().getServletContext();

List<GoodsType> typeList = getList();

servletContext.setAttribute("GOODS_TYPE_LIST",typeList);

}

/**

*

* @Title: getByTypeName

* @Description: 依据商品名称查询

* @param typeName

* @return

* @throws Exception

*/

public GoodsType getByTypeName(String typeName) throws Exception {

return typeDao.getByTypeName(typeName);

}

}

控制层

package com.ahut.action;

import java.util.List;

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

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import com.ahut.entity.GoodsType;

import com.ahut.service.GoodsTypeService;

/**

*

* @ClassName: GoodsTypeAction

* @Description: 商品类型控制层

* @author chengrui

* @date 2017年7月17日 上午11:09:47

*/

@RestController // 等价于@Controller+@ResponseBody

public class GoodsTypeAction {

// 业务逻辑

@Autowired

private GoodsTypeService typeService;

/**

*

* @Title: getGoodsTypeList

* @Description: 获取商品类型列表

* @return

* @throws Exception

*/

@RequestMapping(value = "/getGoodsTypeList")

public List<GoodsType> getGoodsTypeList() throws Exception {

// 调用业务逻辑,返回数据

return typeService.getList();

}

@RequestMapping(value="/getByTypeName")

public GoodsType getByTypeName(String typeName) throws Exception{

typeName = "生活用品";

return typeService.getByTypeName(typeName);

}

}

5.springboot入口

注意:使用了@MapperScan(“com.ahut.mapper”)注解,Mapper接口上就不需要加上@Mapper注解了,两者只用选择其一

package com.ahut;

import java.sql.SQLException;

import java.util.HashMap;

import java.util.Map;

import javax.sql.DataSource;

import org.mybatis.spring.annotation.MapperScan;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.boot.web.servlet.FilterRegistrationBean;

import org.springframework.boot.web.servlet.ServletRegistrationBean;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Primary;

import org.springframework.context.annotation.PropertySource;

import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

import com.alibaba.druid.pool.DruidDataSource;

import com.alibaba.druid.support.http.StatViewServlet;

import com.alibaba.druid.support.http.WebStatFilter;

/**

*

* @ClassName: AhutApplication

* @Description: springboot入口

* @author cheng

* @date 2017年9月24日 下午1:46:51

*/

@SpringBootApplication

@PropertySource(value = { "classpath:mysql.properties" })

@MapperScan("com.ahut.mapper")//扫描数据访问接口

public class AhutApplication extends WebMvcConfigurationSupport {

@Value("${spring.datasource.url}")

private String dbUrl;

@Value("${spring.datasource.username}")

private String username;

@Value("${spring.datasource.password}")

private String password;

@Value("${spring.datasource.driverClassName}")

private String driverClassName;

@Value("${spring.datasource.initialSize}")

private int initialSize;

@Value("${spring.datasource.minIdle}")

private int minIdle;

@Value("${spring.datasource.maxActive}")

private int maxActive;

@Value("${spring.datasource.maxWait}")

private int maxWait;

@Value("${spring.datasource.timeBetweenEvictionRunsMillis}")

private int timeBetweenEvictionRunsMillis;

@Value("${spring.datasource.minEvictableIdleTimeMillis}")

private int minEvictableIdleTimeMillis;

@Value("${spring.datasource.validationQuery}")

private String validationQuery;

@Value("${spring.datasource.testWhileIdle}")

private boolean testWhileIdle;

@Value("${spring.datasource.testOnBorrow}")

private boolean testOnBorrow;

@Value("${spring.datasource.testOnReturn}")

private boolean testOnReturn;

@Value("${spring.datasource.poolPreparedStatements}")

private boolean poolPreparedStatements;

@Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize}")

private int maxPoolPreparedStatementPerConnectionSize;

@Value("${spring.datasource.filters}")

private String filters;

@Value("{spring.datasource.connectionProperties}")

private String connectionProperties;

@Bean // 声明其为Bean实例

@Primary // 在同样的DataSource中,首先使用被标注的DataSource

public DataSource dataSource() {

DruidDataSource datasource = new DruidDataSource();

datasource.setUrl(this.dbUrl);

datasource.setUsername(username);

datasource.setPassword(password);

datasource.setDriverClassName(driverClassName);

// configuration

datasource.setInitialSize(initialSize);

datasource.setMinIdle(minIdle);

datasource.setMaxActive(maxActive);

datasource.setMaxWait(maxWait);

datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);

datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);

datasource.setValidationQuery(validationQuery);

datasource.setTestWhileIdle(testWhileIdle);

datasource.setTestOnBorrow(testOnBorrow);

datasource.setTestOnReturn(testOnReturn);

datasource.setPoolPreparedStatements(poolPreparedStatements);

datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);

try {

datasource.setFilters(filters);

} catch (SQLException e) {

e.printStackTrace();

}

datasource.setConnectionProperties(connectionProperties);

return datasource;

}

@Bean

public ServletRegistrationBean druidServlet() {

ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();

servletRegistrationBean.setServlet(new StatViewServlet());

servletRegistrationBean.addUrlMappings("/druid/*");

Map<String,String> initParameters = new HashMap<String,String>();

initParameters.put("loginUsername","admin");// 用户名

initParameters.put("loginPassword","admin");// 密码

initParameters.put("resetEnable","false");// 禁用HTML页面上的“Reset All”功能

initParameters.put("allow",""); // IP白名单 (没有配置或者为空,则允许所有访问)

// initParameters.put("deny","192.168.20.38");// IP黑名单

// (存在共同时,deny优先于allow)

servletRegistrationBean.setInitParameters(initParameters);

return servletRegistrationBean;

}

@Bean

public FilterRegistrationBean filterRegistrationBean() {

FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();

filterRegistrationBean.setFilter(new WebStatFilter());

filterRegistrationBean.addUrlPatterns("/*");

filterRegistrationBean.addInitParameter("exclusions","*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");

return filterRegistrationBean;

}

/**

* 1、 extends WebMvcConfigurationSupport 2、重写下面方法; setUseSuffixPatternMatch:

*

* 设置是否是后缀模式匹配,如“/user”是否匹配/user.*,默认真即匹配; setUseTrailingSlashMatch:

* 设置是否自动后缀路径模式匹配,如“/user”是否匹配“/user/”,默认真即匹配;

*/

@Override

protected void configurePathMatch(PathMatchConfigurer configurer) {

configurer.setUseSuffixPatternMatch(false).setUseTrailingSlashMatch(true);

}

public static void main(String[] args) {

SpringApplication.run(AhutApplication.class);

}

}

6.事务管理

Spring Boot中推荐使用@Transactional注解来申明事务。

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-jdbc</artifactId>

</dependency>

mybatis-spring-boot-starter会自动引入spring-boot-starter-jdbc依赖,所以不需要在额外添加

当引入jdbc依赖之后,Spring Boot会自动默认分别注入DataSourceTransactionManager或JpaTransactionManager,所以我们不需要任何额外配置就可以用@Transactional注解进行事务的使用。

@Transactional不仅可以注解在方法,也可以注解在类上。当注解在类上时,意味着此类所有public方法都会开启事务。如果类级别和方法级别同时使用了@Transactional注解,则使用在类级别的注解会重载方法级别的注解。

意见反馈 常见问题 官方微信 返回顶部