介绍
这篇文章将介绍springboot2是如何集成mybatis的,并且提供完成的项目代码。所以在文章里,不重要的地方就略过了。想了解详情,可已clone项目自己看看。
动手写代码
创建maven项目order,目录结构如下
domain:存放数据模型、mapper:数据访问、service:服务层、controller:对外接口
pom.xml 添加mybatis依赖和分页插件
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.10</version>
</dependency>
添加数据模型order
package com.bestaone.aiwan.order.domain;
public class Order {
private Long id;
private String no;
private String title;
private Float totalAmount;
private OrderStatus status;
private Date createTime;
...
}
添加数据库
DROP TABLE IF EXISTS `orderx`;
CREATE TABLE `orderx` (
`id` bigint(11) NOT NULL,
`no` varchar(50) DEFAULT NULL,
`title` varchar(50) DEFAULT NULL,
`totalAmount` decimal(19,5) DEFAULT NULL,
`createTime` datetime DEFAULT NULL,
`status` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
由于order是数据库关键字,所有表名使用orderx
编写mapper
mybatis的sql写在java文件和xml文件中都是可以的。
- java文件的写法
@Mapper
public interface OrderMapper {
@Insert("INSERT INTO orderx (id,no,title,totalAmount,createTime,status) VALUES (#{id},#{no},#{title},#{totalAmount},#{createTime},#{status})")
void insert(Order user);
@Delete("DELETE FROM orderx WHERE id = #{id}")
void delete(Long id);
@Update("UPDATE orderx SET no=#{no},title=#{title},totalAmount=#{totalAmount},createTime=#{createTime},status=#{status} WHERE id =#{id}")
int update(Order user);
@ResultMap("BaseResultMap")
@Select("SELECT * FROM orderx WHERE id=#{id}")
Order findById(Long id);
@ResultMap("BaseResultMap")
@Select("SELECT * FROM orderx")
List<Order> findAll();
@ResultMap("BaseResultMap")
@Select("SELECT * FROM orderx WHERE status = #{status}")
List<Order> findByStatus(OrderStatus status);
}
- 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.bestaone.aiwan.user.mapper.RoleMapper">
<resultMap id="BaseResultMap" type="Role" >
<id column="id" property="id" jdbcType="BIGINT" />
<result column="code" property="code" jdbcType="VARCHAR" />
<result column="name" property="name" jdbcType="VARCHAR" />
<result column="description" property="description" jdbcType="VARCHAR" />
</resultMap>
<sql id="Base_Column_List" >
id,name,description
</sql>
<select id="findByUserId" resultMap="BaseResultMap" >
SELECT DISTINCT R.*
FROM sys_role R
LEFT JOIN sys_user_role UR ON UR.roleId=R.id
WHERE UR.userId=#{userId}
</select>
</mapper>
在application.properties中添加mybatis的配置
#扫描路径
mybatis.mapper-locations = classpath:mybatis/mapper/*.xml
#别名包路径
mybatis.type-aliases-package = com.bestaone.aiwan.order.domain
#分页插件配置
pagehelper.helperDialect = mysql
pagehelper.supportMethodsArguments = true
pagehelper.autoRuntimeDialect = true
pagehelper.offsetAsPageNum = true
pagehelper.rowBoundsWithCount = true
pagehelper.reasonable = false
pagehelper.returnPageInfo = true
pagehelper.params = count=countSql
添加service CRUD
@Service
public class OrderServiceImpl implements OrderService {
@Resource
OrderMapper mapper;
@Override
public Order save(Order order) {
if(order.getId()!=null){
mapper.update(order);
} else {
//为了方面,零时这么写下
order.setId(System.currentTimeMillis());
mapper.insert(order);
}
return order;
}
@Override
public Order findById(Long id) {
return mapper.findById(id);
}
@Override
public List<Order> findAll() {
return mapper.findAll();
}
@Override
public void delete(Long id) {
mapper.delete(id);
}
@Override
public List<Order> findByStatus(OrderStatus status) {
return mapper.findByStatus(status);
}
}
添加Controller
@RestController
@RequestMapping("/api/order")
public class OrderController implements OrderApi {
private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
OrderService userService;
//创建order
@Override
@PostMapping
public ApiResponse<String> create(@Valid @RequestBody OrderDto orderDto) throws CommonException {
Assert.notNull(orderDto.getTitle(),50000, "title不存在");
Assert.notNull(orderDto.getTotalAmount(),50000, "totalAmount不存在");
Order order = new Order();
order.setTitle(orderDto.getTitle());
order.setTotalAmount(orderDto.getTotalAmount());
order.setCreateTime(new Date());
order.setStatus(OrderStatus.UNPAY);
userService.save(order);
return ApiResponse.sucess(order.getId().toString());
}
//跟新order
@Override
@PutMapping("/{id:\\d+}")
public ApiResponse update(@PathVariable Long id, @Valid @RequestBody OrderDto orderDto, BindingResult errors) {
Order order = userService.findById(id);
order.setTitle(orderDto.getTitle());
order.setTotalAmount(orderDto.getTotalAmount());
order.setCreateTime(new Date());
order.setStatus(OrderStatus.UNPAY);
userService.save(order);
return ApiResponse.sucess();
}
//删除order
@Override
@DeleteMapping("/{id:\\d+}")
public ApiResponse delete(@PathVariable Long id) {
userService.delete(id);
return ApiResponse.sucess();
}
//查询order
@Override
@GetMapping
public ApiResponse<PageVo<OrderVo>> query(Integer pageNum, Integer pageSize, String status) {
Page pageinfo = PageHelper.startPage(pageNum, pageSize);
List<Order> orders = userService.findByStatus(OrderStatus.valueOf(status));
List<OrderVo> orderVos = new ArrayList<>();
for(Order order : orders){
OrderVo vo = new OrderVo();
vo.setNo(order.getNo());
vo.setTitle(order.getTitle());
vo.setId(order.getId());
vo.setStatus(order.getStatus()!=null?order.getStatus().name():null);
vo.setTotalAmount(order.getTotalAmount());
orderVos.add(vo);
}
return ApiResponse.sucess(new PageVo<>(pageinfo.getPageNum(), pageinfo.getPageSize(),pageinfo.getTotal(),pageinfo.getPages(),orderVos));
}
//获取详情
@Override
@GetMapping("/{id:\\d+}")
public ApiResponse<OrderVo> getInfo(@PathVariable Long id) throws CommonException{
Order order = userService.findById(id);
Assert.notNull(order,20001,"数据不存");
OrderVo vo = new OrderVo();
vo.setNo(order.getNo());
vo.setTitle(order.getTitle());
vo.setId(order.getId());
vo.setCreateTime(order.getCreateTime());
vo.setStatus(order.getStatus()!=null?order.getStatus().name():null);
vo.setTotalAmount(order.getTotalAmount());
return ApiResponse.sucess(vo);
}
}
编辑单元测试测试service、mock测试Controller
- 单元测试
@Transactional //支持数据回滚,避免测试数据污染环境
@RunWith(SpringRunner.class)
@SpringBootTest(classes = OrderApplication.class)
public class OrderServiceTest {
@Autowired
public OrderService service;
@Test
public void CRUDTest() {
//CREATE
Order o = new Order();
o.setTitle("test");
o.setTotalAmount(1F);
o.setCreateTime(new Date());
o.setStatus(OrderStatus.UNPAY);
o.setCreateTime(new Date());
service.save(o);
Assert.assertNotNull(o.getId());
//READ
o = service.findById(o.getId());
Assert.assertNotNull(o.getId());
//UPDATE
o.setTitle("CRUDTest1");
service.save(o);
o = service.findById(o.getId());
Assert.assertTrue(o.getTitle().equals("CRUDTest1"));
//PAGE
PageHelper.startPage(1,1);
List<Order> list = service.findAll();
PageInfo<Order> page = new PageInfo<>(list);
Assert.assertTrue(page.getTotal()>0);
//DELETE
service.delete(o.getId());
o = service.findById(o.getId());
Assert.assertNull(o);
}
}
- mock测试
@WebAppConfiguration
@Transactional //支持数据回滚,避免测试数据污染环境
@RunWith(SpringRunner.class)
@SpringBootTest
public class OrderControllerTest {
private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private WebApplicationContext wac;
@Autowired
private ObjectMapper objectMapper;
private MockMvc mockMvc;
@Before
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
}
@Test
public void whenQuerySuccess() throws Exception {
String result = mockMvc.perform(
get("/api/order")
.param("pageNum", "1")
.param("pageSize", "10")
.param("status", OrderStatus.PAID.name())
.contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(10000))
.andReturn().getResponse().getContentAsString();
logger.debug("返回结果:{}", result);
}
@Test
public void whenGetInfoSuccess() throws Exception {
String result = mockMvc.perform(get("/api/order/1")
.contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(10000))
.andReturn().getResponse().getContentAsString();
logger.debug("返回结果:{}", result);
}
@Test
public void whenGetInfoFail() throws Exception {
String result = mockMvc.perform(get("/api/order/a")
.contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(status().is4xxClientError())
.andReturn().getResponse().getContentAsString();
logger.debug("返回结果:{}", result);
}
@Test
public void whenCreateSuccess() throws Exception {
OrderDto dto = new OrderDto().setTitle("iphone x 1").setTotalAmount(10001F);
String result = mockMvc.perform(post("/api/order").contentType(MediaType.APPLICATION_JSON_UTF8)
.content(objectMapper.writeValueAsString(dto)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(10000))
.andReturn().getResponse().getContentAsString();
logger.debug("返回结果:{}", result);
}
@Test
public void whenCreateFail() throws Exception {
OrderDto dto = new OrderDto();
String result = mockMvc.perform(post("/api/order").contentType(MediaType.APPLICATION_JSON_UTF8)
.content(objectMapper.writeValueAsString(dto)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(50000))
.andReturn().getResponse().getContentAsString();
logger.debug("返回结果:{}", result);
}
@Test
public void whenUpdateSuccess() throws Exception {
OrderDto dto = new OrderDto().setTitle("iphone x 2").setTotalAmount(10001F);
String result = mockMvc.perform(put("/api/order/1").contentType(MediaType.APPLICATION_JSON_UTF8)
.content(objectMapper.writeValueAsString(dto)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(10000))
.andReturn().getResponse().getContentAsString();
logger.debug("返回结果:{}", result);
}
@Test
public void whenDeleteSuccess() throws Exception {
String result = mockMvc.perform(delete("/api/order/1")
.contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(10000))
.andReturn().getResponse().getContentAsString();
logger.debug("返回结果:{}", result);
}
}
编译、测试
cd Aiwan\aiwan-microsvr-order
mvn clean install
#等单元测试完成,大概1分钟
本文源码 https://github.com/bestaone/Aiwan/tree/master/aiwan-microsvr-order