SpringBoot学习-(六)SpringBoot与Mybatis整合
mybatis-spring-boot-starter依赖树如下:
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
项目目录结构如下:
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,jdbcType=VARCHAR},
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, TYPE_NAME, 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, TYPE_NAME, CREATE_TIME,
UPDATE_TIME)
values (#{typeId,jdbcType=VARCHAR}, #{typeName,jdbcType=VARCHAR},
#{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,jdbcType=VARCHAR},
</if>
<if test="typeName != null">
#{typeName,jdbcType=VARCHAR},
</if>
<if test="createTime != null">
#{createTime,jdbcType=TIMESTAMP},
</if>
<if test="updateTime != null">
#{updateTime,jdbcType=TIMESTAMP},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="com.ahut.entity.GoodsType">
update goods_type
<set>
<if test="typeName != null">
TYPE_NAME = #{typeName,jdbcType=VARCHAR},
</if>
<if test="createTime != null">
CREATE_TIME = #{createTime,jdbcType=TIMESTAMP},
</if>
<if test="updateTime != null">
UPDATE_TIME = #{updateTime,jdbcType=TIMESTAMP},
</if>
</set>
where TYPE_ID = #{typeId,jdbcType=VARCHAR}
</update>
<update id="updateByPrimaryKey" parameterType="com.ahut.entity.GoodsType">
update goods_type
set TYPE_NAME = #{typeName,jdbcType=VARCHAR},
CREATE_TIME = #{createTime,jdbcType=TIMESTAMP},
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 // 等价于@aaa@qq.com
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注解,则使用在类级别的注解会重载方法级别的注解。
上一篇: MySQL触发器trigger的使用
下一篇: 浅析前端性能优化总结
推荐阅读
-
SpringBoot学习-(六)SpringBoot与Mybatis整合
-
SpringBoot和Mybatis的整合
-
elastic stack(六) springboot整合es
-
一篇文章带你入门Springboot整合微信登录与微信支付(附源码)
-
springboot整合mybatis连接mysql数据库出现SQLException异常
-
springboot整合mybatis
-
SpringBoot整合mybatis进行快速开发
-
从.Net到Java学习第六篇——SpringBoot+mongodb&Thymeleaf&模型验证
-
SpringBoot无废话入门04:MyBatis整合
-
SpringBoot整合MyBatis获得插入数据后获取主键,返回值总是1