目录
Mybatis主要通过注解和写xml配置文件两种方式来写mysql语句,从而实现CURD操作的。
本篇博客将通过整合spring boot和mybatis的方式记录mybatis的使用方法。
推荐查看官方文档
Mybatis 基本使用流程
引入依赖
mybatis其实就是基于JDBC的封装,所以mysql-connector-java驱动一定要引入的
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
写配置文件
这里只做最基本的配置,更多配置属性可以查阅文档
我这里使用的yml文件作为配置文件
spring:
datasource:
url: jdbc:mysql://127.0.01:3306/tubedb?useUnicode=true&characterEncoding=utf8
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
server:
port: 8080
使用xml文件方式
1.创建实体类
public class User {
private int id;
private int role_id;
private int depart_id;
private String user_name;
private String user_passwd;
private String user_email;
private int phone;
// setter and getter....
}
2.创建一个mapper接口
@Repository
public interface UserMapper {
User selectUserById(int id);
}
@Repository用于标注数据访问组件
3.创建一个contoller
@RestController
public class UserC {
@Autowired
UserMapper userMapper;
@RequestMapping(value = "user",method = RequestMethod.GET)
public User upload(int id){
return userMapper.selectUserById(id);
}
}
4.创建xml文件
在resources目录,创建一个mapper文件夹,在mapper中创建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.example.mybatisdemos.mapper.UserMapper">
<select id="selectUserById" resultType="com.example.mybatisdemos.User">
select * from tm_user where id = #{id}
</select>
</mapper>
注意:
- namespace 指向的是第三步创建mapper UserMapper接口
- select 的id=“” 需要与第三部中的函数名保持一致
5.修改配置文件
在yml配置文件中添加
mybatis:
mapper-locations: classpath:/mapper/*.xml
需要注意
一定配置mybatis.mapper-locations属性指定xml文件的路径,不然会报BindingException异常。
我将xml文件放在resources目录下,如图
6.扫描目录
最后一步需要为spring程序添加@MapperScan注解
@MapperScan("com.example.mybatisdemos.mapper")
@SpringBootApplication
public class MybatisdemosApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisdemosApplication.class, args);
}
}
其value是UserMapper所在包
总结
demo目录结构
使用注解的方式
使用注解的方式虽然功能不如xml的方式强大,但是特别简洁
从写完配置文件那一步开始
1.创建User实体
略
2.创建UserDao接口
@Mapper
@Component
public interface UserDao {
@Select("Select * from tm_user where id=#{id}")
User selectUser(@Param("id") int id);
}
一些博客可能没有使用@Component注解,我在使用过程中发现,如果不加该注解 IDEA是会报错的
3.在Controller中使用
按道理应该加一个Service层的但是省略
@RestController
public class UserC {
@Autowired
UserDao userDao;
@RequestMapping(value = "user",method = RequestMethod.GET)
public User upload(int id){
return userDao.selectUser(id);
}
}
4.配置扫描目录
@MapperScan("com.example.mybatisdemos")
@SpringBootApplication
public class MybatisdemosApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisdemosApplication.class, args);
}
}
如果在Mapper接口中使用了@Mapper注解,这一步其实是可以省略的,如果在这一步使用了@MapperScan那么同理,在接口中可以不使用@Mapper。
最终结果
Mybatis 配置
在spring中mybatis的配置是需要单独写xml文件来完成的,在springboot中一切框架的的配置都可以通过application.yml或者application.properties完成。
mybatis所有配置
XML文件方式详细介绍
xml映射文件
Mybatis的强大之处在于它的映射语句(官方文档说的),但是写一堆xml文件其实也很麻烦。
sql映射文件有以下几个顶级元素
- cache – 对给定命名空间的缓存配置。
- cache-ref – 对其他命名空间缓存配置的引用。
- resultMap – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。
- sql – 可被其他语句引用的可重用语句块。
- insert – 映射插入语句
- update – 映射更新语句
- delete – 映射删除语句
- select – 映射查询语句
在上述顶级元素中还存在多个属性元素,若要熟悉mybatis的使用,也都需要了解。
select
<select id="selectPerson" parameterType="int" resultType="hashmap">
SELECT * FROM PERSON WHERE ID = #{id}
</select>
以上语句可以称之为selectPerson(可以通过它的id调用),参数类型是int,返回类型是hashmap的对象,key就是字段名,value就是结果
其中#{id} 是由用户输入的。
select元素允许配置很多属性来配置每条语句的作用细节。
<select
id="selectPerson"
parameterType="int"
resultType="hashmap"
resultMap="personResultMap"
flushCache="false"
useCache="true"
timeout="10"
fetchSize="256"
statementType="PREPARED"
resultSetType="FORWARD_ONLY">
update、delete、insert
update、delete、insert可用的配置
<insert
id="insertAuthor"
parameterType="domain.blog.Author"
flushCache="true"
statementType="PREPARED"
keyProperty=""
keyColumn=""
useGeneratedKeys=""
timeout="20">
<update
id="updateAuthor"
parameterType="domain.blog.Author"
flushCache="true"
statementType="PREPARED"
timeout="20">
<delete
id="deleteAuthor"
parameterType="domain.blog.Author"
flushCache="true"
statementType="PREPARED"
timeout="20">
如果要使用useGeneratedKeys属性让主键自动生成值,可以useGeneratedKeys=“true” 后再将
keyProperty属性的值设置为主键字段即可
<insert id="insertAuthor" useGeneratedKeys="true"
keyProperty="id">
insert into Author (username,password,email,bio)
values (#{username},#{password},#{email},#{bio})
</insert>
sql
sql元素被用来定义可以重用的sql代码段,这些sql代码段可以被包含在其他语句中。贴个官方的例子吧没什么好说的。
定义
<sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password </sql>
使用
<select id="selectUsers" resultType="map">
select
<include refid="userColumns"><property name="alias" value="t1"/></include>,
<include refid="userColumns"><property name="alias" value="t2"/></include>
from some_table t1
cross join some_table t2
</select>
动态sql语句
通过mybatis xml文件方式经过数据库操作时,可以在xml文件中使用循环标签和条件标签来根据不同条件动态改变mysql语句
官方文档
mybatis提供了if,choose, when, otherwise,foreach,trim, where, set,bind
官方文档说的很详细,就省略了。
其中foreach可以解决mybatis批量插入数据的问题
结果映射
resultMap 元素是 MyBatis 中最重要最强大的元素。它可以让你从 90% 的 JDBC ResultSets 数据提取代码中解放出来
可以使用此方法将结果映射到hashmap上
<select id="selectUsers" resultType="map">
select id, username, hashedPassword
from some_table
where id = #{id}
</select>
但是在实际开发中,大多数情况会使用自己的javaBean or POJO,如果数据库表中字段名和javabean的属性一一对应那么直接替换resultType为你的javaBean即可。
如果无法对应,那么也有很多办法能解决这个问题,但是或许可以试试ResultMap
<resultMap id="userResultMap" type="User">
<id property="id" column="user_id" />
<result property="username" column="user_name"/>
<result property="password" column="hashed_password"/>
</resultMap>
显然property是javabean的属性 而column则是数据库表中的字段名
而在引用它的语句中使用 resultMap 属性就行了(注意我们去掉了 resultType 属性)。比如:
<select id="selectUsers" resultMap="userResultMap">
select user_id, user_name, hashed_password
from some_table
where id = #{id}
</select>
#{} 以及 ${}传递参数
在mybatis参数传递
${} 这种方式容易被sql注入攻击,所以使用的时候需要注意
简单用法
#{id} 里的id没有类型限制你穿什么都可以,简单的用法基本适合九成以上的使用场景
<select id="selectUsers" resultType="User">
select id, username, password
from users
where id = #{id}
</select>
传入对象
我们还可以直接传入一个对象
<insert id="insertUser" parameterType="User">
insert into users (id, username, password)
values (#{id}, #{username}, #{password})
</insert>
通过paramterType指定传入类型为User,之后就可以传入一个User对象,id、username、password属性,会自动在User对象里查找并被传入预处理的语句的参数中。
同时还可以使用javaType确定传入参数的类型,比如:
#{age,javaType=int,jdbcType=NUMERIC}
注意:JDBC 要求,如果一个列允许 null 值,并且会传递值 null 的参数,就必须要指定 JDBC Type。
对于数值参数还可以限制其小数点位数
#{height,javaType=double,jdbcType=NUMERIC,numericScale=2}
字符串替换
默认情况下,使用 #{} 格式的语法会导致 MyBatis 创建 PreparedStatement 参数占位符并安全地设置参数(就像使用 ? 一样)。 这样做更安全,更迅速,通常也是首选做法,不过有时你就是想直接在 SQL 语句中插入一个不转义的字符串,就可以用使用${}来传递参数
其中 ${column} 会被直接替换,而 #{value} 会被使用 ? 预处理。
注解方式
public interface BlogMapper{
@Select("SELECT * FROM blog WHERE id = #{id}")
Blog selectBlog(int id);
}
注解方式我个人比较喜欢,简洁优美,在使用中灵活变通其实还是非常好用的
注解的骚操作
通过注解方式写mysql语句其中#{} 其实不仅仅可以用来传值,还可以用于传mysql语句
在项目最开始,我便用的注解方式,但是涉及到批量插入的问题,我想到的方法:
- service层循环调用插入语句
其结果就是,插入速度非常缓慢。
因此我就转而使用了xml方式,但是注解方式能不能批量插入其实也可以的
@Insert("INSERT INTO tm_tube_log (user_id,tube_code,action_id,img_tb_id,img_user_id,datetime,uses_txt) VALUES ${yifaruhun}")
public int insertTubeByOneCodeLog(@Param("yifaruhun")String yifaruhun);
具体操作是通过service层将要插入的多个数据拼接成
(,),(,),(,),(,),(,)…的形式,在接口方法中,一发入魂!
但是这里需要注意,采用这种方法就不能使用#{}而要使用${} ,避免将sql语句转义,但是这样一来就需要考虑sql注入攻击的问题了。