前言
之前,在spring boot篇中就遇到了启动失败的问题,原因呢就是自动加载数据源失败,当时呢,是用下面这一句,取消自动加载数据源先回避了这个问题,现在呢,要引入mybatis,我们的数据源自然是要配置配置了。
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
同理,再开始之前,我们先摆出我的资料。spring boot+mybatis整合,mybatis,SpringBoot数据源配置,ok,大致阅读了一下资料,有个底了。
1.引入依赖
因为新建项目的时候选了Mybatis,所以依赖是已经有了的,就算没点,百度一下Mybatis的依赖也很简单。
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.0.0'
2.数据源配置
看完之后脑子里印象最深的就是这个了。在resource目录下,新建application.yml配置文件。好了把@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)更改为@SpringBootApplication() 进行启动。报错,提示com.mysql.jdbc.Driver需要更换为com.mysql.cj.jdbc.Driver。按提示修改,启动正常说明数据源接入成功了。
#数据源配置 jdbc
spring:
datasource:
url: jdbc:mysql://localhost:3307/ticketsellingsystem?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
driverClassName: com.mysql.cj.jdbc.Driver
username: root
password: 123456
#mybatis配置
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: org.ironman.ticketsellingsystem.entity
type-handlers-package: org.ironman.ticketsellingsystem.dao
上述配置理解应该很容易,都是常见的。
url:数据库地址。
driverClassName:驱动,jdbc。
username:数据库账号。
password:数据库密码。
mapper-location:mybatis写了sql语句的xml文件路径。
type-aliasses-package:实体类的路径
type-handlers-package:dao的路径。
其实还有很多的配置可以设置,但是,现在的话,我们只需要这么多就行了。当然这也只是配置数据源其中的方式之一。
当然配置也是不止这么点,例如URL的最后一位。
&serverTimezone=UTC
前面写的时候,我是没有加的,后来写demo的时候报错了,说是什么数据库时区设置问题,就加上了这一条。
3.简单demo
因为手里头有现成的项目,也有搞web的同学的demo,所以对具体的流程,还是略有了解的,我们就简单的来一个查询语句走一遍吧。
第一步,数据库建了个表。
第二步,对应的实体类。TestEntity,注意与数据库的表属性名一致哦,不然肯定会出错的。
package org.ironman.ticketsellingsystem.entity;
public class TestEntity {
private int id;
private String username;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
第三步,dao层。用mybatis其实就是写了一下接口,每个方法都是一个操作,如下,是一个查询操作。
package org.ironman.ticketsellingsystem.dao;
import org.ironman.ticketsellingsystem.entity.TestEntity;
public interface TestDao {
TestEntity selectUserName(int id);
}
这里的话,形参,是你查询条件需要的数据,而返回值的类型,你可以自定义。单个可以直接用实体类,多个则用List<entity>这种形式,其他的,慢慢学吧。
第四步,sql语句,mybatis的sql语句是存放在xml文件中的,而这些xml文件,则是存放在之前mybatis配置中设置的文件路径下。基本上一个dao,对应一个mybatis的mapper.xml。
ok,我们在resource/mapper文件夹下,新建一个TestDaoMapper.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="org.ironman.ticketsellingsystem.dao.TestDao">
<select id="selectUserName" parameterType="int" resultType="TestEntity">
select * from test where id = #{id}
</select>
</mapper>
一个简单的查询操作如上所示。ok,这些东西都挺重要的,有半点差错,就肯定会报错,我是踩了。
namespace:命名空间一定要定位到指定的Dao,不然会有Mapper失败的情况。如这里是TestDao。
id:TestDao中对应的方法名,必须一致。
parameterType:输入数据类型与形参一致
resultType:输出数据类型与返回值类型一致
#{id}: TestDao中的形参名,相当于以前的用的 ?标签。查询条件的值就靠它了。
第五步,service,首先定义一些接口,然后实现它,一般实现类反正service下的impl下,后缀也加上Impl
package org.ironman.ticketsellingsystem.service;
import org.ironman.ticketsellingsystem.entity.TestEntity;
public interface TestService {
TestEntity getUserNameById(int id);
}
package org.ironman.ticketsellingsystem.service.impl;
import org.ironman.ticketsellingsystem.dao.TestDao;
import org.ironman.ticketsellingsystem.entity.TestEntity;
import org.ironman.ticketsellingsystem.service.TestService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service("TestService")
public class TestServiceImpl implements TestService {
@Resource
private TestDao testDao;
@Override
public TestEntity getUserNameById(int id) {
//业务逻辑代码
return testDao.selectUserName(id);
}
}
TestService:没什么好说的,应该就是定义一系列逻辑操作的接口,例如定义一个检查账号密码是否正确的方法,一个查询的方法,要在检查账号登录之后查询查询,当然这些方法要在TestServiceImpl类中实现它。然后有两个注解@Service和@Resource,如果要正常使用肯定是配置注解的,所以很重要。
第六步,模板页面,前面我们在引入模板引擎的时候就写好了这个界面。test.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></meta>
<title>im test page</title>
</head>
<body>
<p th:text="${hello}">Welcome to our grocery store!</p>
</body>
第七步,controller,修改一下我们之前的TestController,将数据替换为从数据中查询的数据。
package org.ironman.ticketsellingsystem.controller;
import org.ironman.ticketsellingsystem.entity.TestEntity;
import org.ironman.ticketsellingsystem.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.HashMap;
import java.util.Map;
//@Controller 和 @RestController 是有区别的。@RestController 相当于@Controller+@ResponseBody
@Controller
public class TestController {
@Autowired
private TestService testService;
@RequestMapping("/test")
public String index(Model model) {
TestEntity testEntity=testService.getUserNameById(1);
// model.addAttribute("hello", "hello world");
model.addAttribute("hello", testEntity.getUsername());
return "test";
}
}
运行后,结果如下,显示的数据与数据库中存储的一致,ok,我们的mybatis就算是引入成功了。
最后,贴一下现在我们的项目结构。
2019.3.12日补充
1.@Param注解,如下:当有多个形参时,需要用该标签帮助myBatista锁定属性。
ps:可将形参设置成对应实体类简化操作。需要在Mapper.xml做映射操作(resultmap标签)(后续整理)
public interface UserDao {
//检查账号密码是否正确
boolean checkLogin(@Param("account")String account, @Param("password")String password);
//检查该账号是否被注册
boolean checkRegister(String account);
}
2.特殊使用,使用count统计数量配合boolean可实现返回true或者false的效果。
<!--通过返回值的数量判断返回true还是false,多个标识时,在dao中需要用@Param标签标识-->
<select id="checkLogin" parameterType="String" resultType="boolean">
select count(id)from user where account = #{account}and password= #{password}
</select>
3.直接向项目中引入mybatis代码自动生成插件需谨慎,反正我是中招了,导致项目启动不了,可能原因,某个地方的配置gg了,也可能是某个<select>标签内的id标错了,总之这样容易产生很多问题。推荐用法,建一个专门的项目,生成后再复制过去,(刚刚问了下我的同学,是的,好像都是这样做的),每次新项目只要改下配置文件,和数据库表映射就ok了。(后续整理)
4.Dao层中的返回值设置。mybatis数据库操作的返回值
insert:返回值是:新插入行的主键(primary key);需要包含<selectKey>语句,才会返回主键,否则返回值为null。
update/delete:返回值是:更新或删除的行数;无需指明resultClass;但如果有约束异常而删除失败,只能去捕捉异常。
queryForObject:返回的是:一个实例对象或null;需要包含<select>语句,并且指明resultMap;
queryForList:返回的是:实例对象的列表;需要包含<select>语句,并且指明resultMap;
如下,insert操作,返回值设定为int用来匹配对应主键。
//返回值是插入操作的主键
int insertUser(UserEntity userEntity);
2019.3.19日补充
1.实际中使用mybatis很容易出现mapping.xml中id重复,或者与dao中方法名不一致的问题,这些都会导致项目启动失败。
2.使用resultmap。
<resultMap id="BaseResultMap" type="org.ironman.ticketsellingsystem.entity.UserEntity">
<id column="id" property="id" jdbcType="INTEGER"/>
<result column="account" property="account" jdbcType="CHAR"/>
<result column="password" property="password" jdbcType="CHAR"/>
<result column="name" property="name" jdbcType="VARCHAR"/>
<result column="age" property="age" jdbcType="INTEGER"/>
<result column="id_card" property="idCard" jdbcType="INTEGER"/>
<result column="sex" property="sex" jdbcType="VARCHAR"/>
<result column="phone" property="phone" jdbcType="VARCHAR"/>
<result column="type" property="type" jdbcType="VARCHAR"/>
<result column="emal" property="emal" jdbcType="CHAR"/>
<result column="state" property="state" jdbcType="VARCHAR"/>
</resultMap>
id:标识
type:数据库做映射的对应实体类。
column:数据库中的列名。
property:实体类中的属性名。
jdbcType:数据库的数据类型
使用如下,通过resultMap指定对应的映射,便可以将数据库返回的结果存放到指定的对象中去了。
<select id="selectUser" parameterType="int" resultMap="BaseResultMap">
select * from user where id= #{id}
</select>
ps:若是在数据库操作中,未指定resultMap,而是使用的resultType。则实体类属性名需要与数据库列名完全一致才能取值成功,或者使用别名亦可。
2019.3.26日补充
当数据库使用了date 等时间格式的数据,我们需要在对应的实体类中做对应配置。
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
private Date trainTime;
@DateTimeFormat:指明时间格式,意料之外的是使用如下代码指定格式会无法查出数据。原因不详。
@DateTimeFormat(pattern = "yyyy-MM-dd")
2019.3.27日补充
resultMap resultType 标签中都是指定数据类型,而不是集合类,哪怕dao中设置的参数为集合类,我们仍然是设定他集合类存的数据类型。