SpringBoot学习-(六)SpringBoot与Mybatis整合
来源:互联网 发布:emplace_back源码 编辑:程序博客网 时间:2024/05/18 12:35
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 // 等价于@Controller+@ResponseBodypublic 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注解,则使用在类级别的注解会重载方法级别的注解。
- SpringBoot学习-(六)SpringBoot与Mybatis整合
- SpringBoot学习:SpringBoot整合mybatis
- springboot与mybatis整合
- springboot学习(6)springboot整合Mybatis例子
- springboot学习(6)springboot整合Mybatis例子
- 【系统学习SpringBoot】springBoot整合Mybatis
- springboot学习笔记(六) Mybatis
- springBoot与MyBatis整合示例
- springboot与mybatis的整合
- springboot与mybatis的整合
- SpringBoot(五):SpringBoot整合MyBatis
- Spring Boot干货——(六)SpringBoot整合mybatis
- SpringBoot整合Mybatis(二)
- SpringBoot学习-(十七)SpringBoot整合Shiro
- SpringBoot学习-(十八)SpringBoot整合EhCache
- springBoot(四)整合之MyBatis整合
- (4)学习SpringBoot之整合 Mybatis+PageHelper分页
- SpringBoot学习(五)——整合MyBatis
- MySQL5.7 安装
- 【PB登陆的实现】
- Matlab中如何把m文件默认打开方式设成editor
- Springmvc和struts2的区别
- 栈的探究
- SpringBoot学习-(六)SpringBoot与Mybatis整合
- 【C#机房重构】用户sa失败-管道的另一端上无任何进程-无法找到表0
- win32飞机大战
- SQLAlchemy的基本使用
- 单例模式
- Matplotlib 入门(三):多图合并
- C#如何根据字符串动态的创建对象(类)
- 二分搜索树(一)
- 最大比合并算法 (Maximal Ratio Combining, MRC)