基于注解-简单
1、 引入依赖
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
2、 在启动类上加@MapperScan(“com.twx.db”)注解,告诉SpringBoot去哪找Mapper
@SpringBootApplication
@MapperScan("com.twx.db")
public class SpringBootEtlApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootEtlApplication.class, args);
}
}
3、 在com.twx.db包下,新建一个接口 MonitorMapper,如下:
package com.twx.db;
import com.twx.entity.WarnEntity;
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface MonitorMapper {
/**
* SQL语句中的变量 用#{}括起来,变量的名称要和方法参数里的注解@Param()中的一样。
* 如下: #{warningTitle} == @Param("warningTitle")
* @Result: 用来映射实体属性和表的字段
*/
@Select("SELECT j.JobMasterID,w.WarningTitle,w.WarningType,j.IsActivated " +
" FROM WarningTemplate w INNER join JobMaster j ON w.WarningCode = j.WarningCode " +
" WHERE WarningTitle LIKE #{warningTitle} and w.WarningType=#{warningType} and j.IsActivated=#{isActivated}")
@Results({
@Result(property = "jobMasterId",column = "JobMasterID",javaType = Integer.class),
@Result(property = "warningTitle",column = "WarningTitle",javaType = String.class),
@Result(property = "warningType",column = "WarningType",javaType = String.class),
@Result(property = "isActivated",column = "IsActivated",javaType = Boolean.class)
})
List<WarnEntity> query(@Param("warningTitle") String warningTitle,@Param("warningType") String warningType, @Param("isActivated") boolean isActivated);
@Select("SELECT j.JobMasterID,w.WarningTitle,w.WarningType,j.IsActivated,j.JsonParameter,j.Version " +
" FROM WarningTemplate w INNER join JobMaster j ON w.WarningCode = j.WarningCode " +
" WHERE j.JobMasterID=#{jobMasterId}")
@Results({
@Result(property = "jobMasterId",column = "JobMasterID",javaType = Integer.class),
@Result(property = "warningTitle",column = "WarningTitle",javaType = String.class),
@Result(property = "warningType",column = "WarningType",javaType = String.class),
@Result(property = "isActivated",column = "IsActivated",javaType = Boolean.class),
@Result(property = "jsonParameter",column = "JsonParameter",javaType = String.class),
@Result(property = "version",column = "Version",javaType = Integer.class)
})
WarnEntity edit(Integer jobMasterId);
}
@Data
public class WarnEntity {
/** Job表主键 */
private Integer jobMasterId;
/** 预警名称 */
private String warningTitle;
/** 预警类型 */
private String warningType;
/** 启用状态 */
private Boolean isActivated;
/** 详细内容 */
private String jsonParameter;
/** 版本号 */
private Integer version;
}
4、 单元测试
package com.twx.db;
import com.twx.entity.WarnEntity;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
import static org.junit.Assert.*;
@RunWith(SpringRunner.class)
@SpringBootTest
public class MonitorMapperTest {
@Autowired
private MonitorMapper monitorMapper;
@Test
public void query() throws Exception {
List<WarnEntity> tasks = monitorMapper.query("%集装箱%", "WaitDoingTask",true);
Assert.assertNotEquals(0,tasks.size());
}
@Test
public void edit() {
WarnEntity edit = monitorMapper.edit(10);
Assert.assertNotNull(edit);
}
}
基于注解-动态注入
上面例子中的sql都是静态的(意味着不需要动态拼接),但是现在我们需要根据传入参数的值来动态的拼接SQL.
怎么做呢?
现在不用@Select 而是要用 @SelectProvider (类似的还有@UpdateProvider @DeleteProvider @InsertProvider)
看下面的这段代码:
@SelectProvider(type = MonitorProvider.class,method = "query")
List<WarnEntity> query(String warningTitle,List<String> warningTypes, List<Boolean> activateLists,int page,int size);
现在我们没在方法定义上写一大堆sql 和 @Results了。而是用 @SelectProvider(type = MonitorProvider.class,method = "query")
代替。 在类 MonitorProvider.class 的 query()方法中去拼接我们的SQL.
来看看是怎么拼SQL的。
public class MonitorProvider {
public String query(Map<String,Object> map){
String title = (String) map.get("arg0");
List<String> types = (List<String>) map.get("arg1");
List<Boolean> activates = (List<Boolean>) map.get("arg2");
int page = (int)map.get("arg3");
int size = (int)map.get("arg4");
int offset = (page-1)*size;
String sql = "SELECT j.JobMasterID,w.WarningTitle,w.WarningType,j.IsActivated "+
" FROM WarningTemplate w INNER join JobMaster j ON w.WarningCode = j.WarningCode "+
"WHERE WarningTitle LIKE \'"+title+"\' and w.WarningType in ("+list2StringByComma(types)+") " +
"and j.IsActivated in ("+boolean2List(activates)+")"+
" ORDER BY j.JobMasterID OFFSET "+(offset)+" ROWS FETCH NEXT "+size+" ROWS ONLY";
return sql;
}
}
在这里我们传入的参数是 MapString warningTitle,List<String> warningTypes, List<Boolean> activateLists,int page,int size
这些参数提取出来的。
没错,arg0 arg1 arg2 arg3 arg4 …呵呵,很傻吧。
剩下的工作就是拼接 SQL 语句了,这里我个人觉得很烦。看title那里,前后还要加个 单引号 。累觉不爱。
所以,这一块,我还要看看别人是怎么做的。
或许用xml方式会简单点。(在拼接SQL的过程中,我都有点想放弃mybatis了,真的很累)。还要继续学习啊!!
好,那就来看xml是怎么写的吧!
基于xml
pom文件中的引入不需要变化,如上就可以了。。。
1、 修改 application.yml文件,告诉springboot去哪找mybatis的xml文件
mybatis:
mapper-locations: classpath:mapper/*.xml
2、 在基于注解的动态SQL中,我们是这样声明接口的
@SelectProvider(type = MonitorProvider.class,method = "query")
List<WarnEntity> query(String warningTitle,List<String> warningTypes, List<Boolean> activateLists,int page,int size);
然后在MonitorProvider的query方法中手动拼接SQL字符串,这种方法很累,要特别注意拼接时的空格、引号。其实官方提供了new SQL() 的java方法,但是我没找到有IN(),所以就放弃了。
现在我们来看在xml中怎么配置query方法吧!
现在query()方法的声明是这样的:
List query(MonitorQueryParam param);
查询参数是个对象 MonitorQueryParam。它长下面这样:
package com.twx.db.param;
import lombok.Data;
import java.util.List;
@Data
public class MonitorQueryParam {
private String warningTitle;
private List<String> warningTypes;
private List<Boolean> activateLists;
private int offset;
private int size;
}
该对象对应的属性名,其实就是我们之前定义query方法时的参数啦~
3、 在claspath下新建个mapper目录,然后新建个MonitorMapper.xml。(看xml中的解释)
<?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.twx.db.MonitorMapper">
<!-- 这里的id: query 对应的是MonitorMapper中的方法名 -->
<!-- 我把select的结果 as 成了 WarnEntity的属性名,这样mybatis就能自动帮我们封装成对象了 -->
<!-- 现在的in (?,?,?) 中的变量 用foreach循环出来,不需要再手动加单引号,逗号和圆括号了,开心! -->
<select id="query" parameterType="com.twx.db.param.MonitorQueryParam" resultType="WarnEntity">
SELECT j.JobMasterID as jobMasterId,
w.WarningTitle as warningTitle,
w.WarningType as warningType,
j.IsActivated as isActivated
FROM WarningTemplate w INNER join JobMaster j ON w.WarningCode = j.WarningCode
WHERE WarningTitle LIKE #{warningTitle}
AND w.WarningType in
<foreach collection="warningTypes" item="type" open="(" close=")" separator=",">
#{type}
</foreach>
AND j.IsActivated in
<foreach collection="activateLists" item="activate" open="(" close=")" separator=",">
#{activate}
</foreach>
ORDER BY j.JobMasterID OFFSET #{offset} ROWS FETCH NEXT #{size} ROWS ONLY
</select>
</mapper>
4、 单元测试
@Test
public void query() throws Exception {
MonitorQueryParam param = new MonitorQueryParam();
param.setWarningTitle("%集装箱%");
param.setWarningTypes(Arrays.asList("WaitDoingTask"));
param.setActivateLists(Arrays.asList(true,false));
param.setOffset(0);
param.setSize(5);
List<WarnEntity> tasks = monitorMapper.query(param);
Assert.assertNotEquals(0,tasks.size());
}
5、 对了,如果我想要再测试时,看到mybatis生成的sql语句,该怎么办呢?
很简单,在logback中把com.twx.db包的日志级别设置成 trace就行了
<logger name="com.twx.db" level="trace" />
另外再举个例子,在xml中使用 resultMap
1、 在 dao包下新建个接口 OrderMasterMapper
package com.twx.springbootmybatis.dao;
import org.apache.ibatis.annotations.Mapper;
import com.twx.springbootmybatis.entity.OrderMaster;
@Mapper
public interface OrderMasterMapper {
OrderMaster findByOrderId(String orderId);
}
注意要加个@Mapper注解,不然@Autowired时会提示.(或者在启动类上加@MapperScan)No qualifying bean of type 'com.twx.springbootmybatis.dao.OrderMasterMapper' available
2、 xml文件 (classpath:mapper/OrderMasterMapper.xml)
<?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.twx.springbootmybatis.dao.OrderMasterMapper">
<!--OrderMaster这里我们写了类的完整路径,每次这样写多麻烦啊。-->
<!--如果我们只写OrderMaster会怎样呢?当然会提示找不到OrderMaster类啊-->
<!--所以 得在application.yml配置一下啊,加上这么一句:-->
<!--mybatis.type-aliases-package: com.twx.springbootmybatis.entity-->
<resultMap id="orderMasterMap" type="com.twx.springbootmybatis.entity.OrderMaster">
<id column="order_id" property="orderId" jdbcType="VARCHAR"></id>
<result column="buyer_name" property="buyerName" jdbcType="VARCHAR"></result>
<result column="buyer_phone" property="buyerPhone" jdbcType="VARCHAR" />
<result column="buyer_address" property="buyerAddress" jdbcType="VARCHAR" />
<result column="buyer_openid" property="buyerOpenid" jdbcType="VARCHAR" />
<result column="order_amount" property="orderAmount" jdbcType="DECIMAL" />
<result column="order_status" property="orderStatus" jdbcType="TINYINT" />
<result column="pay_status" property="payStatus" jdbcType="TINYINT" />
<result column="create_time" property="createTime" jdbcType="TIMESTAMP" />
<result column="update_time" property="updateTime" jdbcType="TIMESTAMP" />
</resultMap>
<select id="findByOrderId" parameterType="String" resultMap="orderMasterMap">
SELECT * FROM order_master WHERE order_id = #{orderId}
</select>
</mapper>
3、 对应的OrderMaster.java
package com.twx.springbootmybatis.entity;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
@Data
public class OrderMaster {
private String orderId;
private String buyerName;
private String buyerPhone;
private String buyerAddress;
/** 微信ID */
private String buyerOpenid;
/** 订单总价 */
private BigDecimal orderAmount;
/** 订单状态 */
private Integer orderStatus;
/** 支付状态 */
private Integer payStatus;
/** 创建时间 */
private Date createTime;
/** 更新时间 */
private Date updateTime;
}
5、 单元测试
package com.twx.springbootmybatis.dao;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Map;
import static org.junit.Assert.*;
@RunWith(SpringRunner.class)
@SpringBootTest
public class OrderMasterMapperTest {
@Autowired
private OrderMasterMapper masterMapper;
@Test
public void findByOrderId() throws Exception {
OrderMaster orderMaster = masterMapper.findByOrderId("123321");
System.out.println(orderMaster);
Assert.assertNotNull(orderMaster);
}
}