MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。
MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。
MyBatis 可以通过简单的 XML 或 注解 来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
用一句简单的话来概述: MyBatis 是更简单完成程序和数据库交互的工具或 MyBatis 是更简单的操作和读取数据库工具
create database if not exists MyBlogSystem;
use MyBlogSystem;
drop table if exists blog;
-- 创建一个博客表
create table blog (
blogId int primary key auto_increment,
title varchar(1024),
content mediumtext,
postTime datetime,
userId int
);
drop table if exists user;
-- 创建一个用户信息表
create table user (
userId int primary key auto_increment,
username varchar(128) unique,
password varchar(128)
);
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
spring.datasource.url=jdbc:mysql://localhost:3306/MyBlogSystem?characterEncoding=utf8&useSSL=true
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
配置 mybatis 的文件路径, 在 resources/mapper 创建所有表的xml文件
mybatis.mapper-locations=classpath:mapper/**Mapper.xml
这里必须要一样
添加用户的实体类
@Getter
@Setter
@ToString
public class User {
public int userId;
public String username;
public String password;
}
@Mapper
public interface UserMapper {
List<User> getAll();
}
固定的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.demo.mapper.UserMapper">
</mapper>
这里的 UserMapper.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.demo.mapper.UserMapper">
<select id="getAll" resultType="com.example.demo.model.User">
select * from user;
</select>
</mapper>
@Service
public class UserService {
// 记得要注入
@Resource
private UserMapper userMapper;
public List<User> getAll() {
return userMapper.getAll();
}
}
// 这里的 @RestController 相当于 @Controller + @ResponseBody
@RestController
@RequestMapping("/user")
public class UserController3 {
@Autowired
private UserService userService;
@RequestMapping("/getall")
public List<User> getAll() {
return userService.getAll();
}
}
注意配置文件中的mapper配置和mapper文件夹的对应
UserMapper.xml 这里需要一些路径对应, 以及id格式对应 , 这里的resultType是返回的类型.
步骤:
① 添加 controller 实现代码
@RestController
@RequestMapping("/user")
public class UserController3 {
@Autowired
private UserService userService;
@RequestMapping("/insert")
public Integer insert(User user) {
return userService.insert(user);
}
}
② 添加 service 实现代码
@Service
public class UserService {
// 记得要注入
@Resource
private UserMapper userMapper;
public Integer insert(User user) {
return userMapper.insert();
}
}
③ 添加 mapper 接口
@Mapper
public interface UserMapper {
Integer insert();
}
④ 添加 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.demo.mapper.UserMapper">
<insert id="insert">
insert into user values (null, #{username},#{password});
</insert>
</mapper>
⑤ 测试代码
步骤:
① 添加 controller
@RequestMapping("/getall")
public List<User> getAll() {
return userService.getAll();
}
② 添加 service
@RequestMapping("/getall")
public List<User> getAll() {
return userService.getAll();
}
③ 添加 mapper 接口
public List<User> getAll() {
return userMapper.getAll();
}
④ 添加 xml
<select id="getAll" resultType="com.example.demo.model.User">
select * from user;
</select>
⑤ 测试代码
步骤:
① 添加controller
@RequestMapping("/update")
public Integer update(Integer userId, String password) {
return userService.update(userId,password);
}
② 添加 service
public Integer update(Integer userId, String password) {
return userMapper.update(userId,password);
}
③ 添加 mapper 接口
Integer update(Integer userId, String password);
④ 添加 xml
<update id="update">
update user set password=#{password} where userId=#{userId}
</update>
⑤ 测试代码
步骤:
① 添加 controller
@RequestMapping("/delete")
public Integer delete(Integer userId) {
return userService.delete(userId);
}
② 3.4.2 添加 service
public Integer delete(Integer userId) {
return userMapper.delete(userId);
}
③ 添加 mapper 接口
Integer delete(Integer userId);
④ 添加 xml
<delete id="delete">
delete from user where userId=#{userId}
</delete>
⑤ 测试代码
这里用增加操作来进行演示
@RequestMapping("/insert2")
public Integer insert2(User user) {
if (user == null || user.getUsername() == null
|| user.getPassword() == null
|| user.getUsername().equals("")
|| user.getPassword().equals("")
) { // 非法参数
return 0;
}
userService.insert2(user);
return user.getUserId();
}
public void insert2(User user) {
userMapper.insert2(user);
}
void insert2(User user);
注意: 如果要返回自增id, 就不能像普通增加那样写xml
正确写法:
<insert id="insert2" useGeneratedKeys="true" keyProperty="userId" keyColumn="userId">
insert into user values (null,#{username}, #{password});
</insert>
一对一的表映射要使用 <association>
标签, 具体实现
<resultMap id="baseMap" type="com.example.demo.model.User">
<!-- 主键映射 -->
<id column="userId" property="userId"></id>
<!-- 普通映射 -->
<result column="username" property="username"></result>
<result column="password" property="password"></result>
</resultMap>
<resultMap id="BaseMap" type="com.example.demo.model.Blog">
<id column="blogId" property="blogId"></id>
<result column="title" property="title"></result>
<result column="content" property="content"></result>
<result column="postTime" property="postTime"></result>
<result column="userId" property="userId"></result>
<association property="user"
resultMap="com.example.demo.mapper.UserMapper.baseMap"
columnPrefix="u_">
</association>
</resultMap>
<select id="getAll" resultMap="BaseMap">
select b.*,u.userId u_userId,u.username u_username,u.password u_password from blog b left join user u on u.userId=b.userId
</select>
注意事项:
property
属性: 指定 Blog 表中对应的属性名, 与实体类一致, 这里是userresultMap
属性: 指定关联的结果集映射, 将基于该映射配置来组织用户数据columnPrefix
属性: 绑定一对一对象时, 多表前缀, 作用防止多张表出现相同字段查询的问题@Data
public class Blog {
public int blogId;
public String title;
public String content;
public Timestamp postTime;
public int userId;
public User user;
}
@RequestMapping("/getall")
public List<Blog> getAll() {
return userService.getAll();
}
public List<Blog> getAll() {
return userMapper.getAll();
}
List<Blog> getAll();
一对多使用 <collection>
标签, 用法和 <association>
相同
<resultMap id="BaseMap2" type="com.example.demo.model.Blog">
<id column="blogId" property="blogId"></id>
<result column="title" property="title"></result>
<result column="content" property="content"></result>
<result column="postTime" property="postTime"></result>
<result column="userId" property="userId"></result>
<collection property="user"
resultMap="com.example.demo.mapper.UserMapper.baseMap"
columnPrefix="u_">
</collection>
</resultMap>
<select id="getUserById" resultMap="BaseMap2">
select b.*,u.username u_username,u.userId u_userId,u.password u_password from blog b left join user u on b.userId=u.userId where u.userId=#{userId}
</select>
@RequestMapping("/getUserById")
public List<Blog> getUserById(Integer userId) {
return userService.getUserById(userId);
}
public List<Blog> getUserById(Integer userId) {
return userMapper.getUserById(userId);
}
List<Blog> getUserById(Integer userId);
#{}
: 预编译处理${}
: 字符直接替换编译预处理: MyBatis 在处理 #{}
时, 会将SQL 中的 #{}
替换为 ?
号, 使用 PreparedStatement
的 set
方法来赋值.
字符直接替换: MyBatis 在处理 ${}
时, 就是把 ${}
替换成变量的值.(缺点SQL注入)
注意: 当使用 #{}
的时候, 传递值为 String
则会加单引号. 使用${}
的时候, 就不会加单引号
在对一些商品进行排序的时候, 使用${}就可以, 而使用#{}就不行
<select id="getall2" resultType="com.example.demo.model.User">
select * from user order by userId ${sort};
</select>
<select id="getAll3" resultType="com.example.demo.model.User">
select * from user where username= '${username}' and password='${password}'
</select>
当注入 'or 1='1
时, 所有的信息就暴露了
需要用户传递的就尽量使用 #{}
, 程序员自己传递的就可以使用 ${}
like 使用 #{}
会报错
例如一段sql代码select * from user where username like '%#{username}%'
;
当username=admin
相当于select * from user where username like '%'admin'%'
这里也不能直接使用 ${}
.
可以使用mysql内置函数 concat()
来处理
<select id="findLike" resultType="com.example.demo.model.User">
select * from user where username like concat('%',#{username},'%')
</select>
例如:
这里就查询不到 name了
除了把名字改过来, 还可以使用 resultMap
<resultMap id="baseMap" type="com.example.demo.model.User">
<!-- 主键映射 -->
<id column="userId" property="userId"></id>
<!-- 普通映射 -->
<result column="username" property="name"></result>
<result column="password" property="password"></result>
</resultMap>
<select id="getAll" resultMap="baseMap">
select * from user
</select>
注意这里的resultMap的写法
在配置文件中添加代码
logging.level.com.example.demo=debug
mybaits.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
通过这样配置就能查看日志了
搜索 MyBatisX
下载之后 重启Idea
有这种鸟就是安装好了
在填写表单的时候 经常会有一些字段必须要填写, 一些字段不必要填写, 那么这种情况就需要用的动态SQL的if标签
xml的演示
<insert id="insert4" useGeneratedKeys="true" keyColumn="blogId" keyProperty="blogId">
insert into blog(
title,
<if test="content != null">
content,
</if>
postTime,userId) values (#{title},
<if test="content != null">
#{content},
</if>
#{postTime},#{userId})
</insert>
注意这里的 if标签后面的test中的content是传入的属性,不是数据库中的字段.
当所有字段都是非必填项, 此时使用 if 标签就满足不了了
如 title是必填项, 后面都是非必填项, 此时sql拼装出来 就会变成insert into blog(title,) values (title,)
这里的逗号就会导致sql报错.<trim>
标签中有如下属性:
prefix
: 表示整个语句块, 以prefix
的值作为前缀suffix
: 表示整个语句块, 以suffix
的值作为后缀prefixOverrides
: prefixOverrides
的值表示整个语句块要去掉的前缀suffixOverrides
: suffixOverrides
的值表示整个语句块要去掉的后缀<insert id="insert5" useGeneratedKeys="true" keyProperty="userId" keyColumn="userId">
insert into blog
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="title != null">
title,
</if>
<if test="content != null">
content,
</if>
<if test="postTime != null">
postTime,
</if>
<if test="userId != null">
userId,
</if>
</trim>
values
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="title != null">
#{title},
</if>
<if test="content != null">
#{content},
</if>
<if test="postTime != null">
#{postTime},
</if>
<if test="userId != null">
#{userId},
</if>
</trim>
</insert>
如代码 select * from blog where userId=#{userId}
如果这里的 userId 是非必填项, 为空, 那么sql也会报错
下面的<where>
标签也可以使用<trim prefix="where" prefixOverrides="and">
替换。
<select id="selectAll" resultType="com.example.demo.model.User">
select * from blog
<where>
<if test="blogId != null">
blogId = #{blogId}
</if>
<if test="userId != null">
and userId = #{userId}
</if>
</where>
</select>
<where>
标签, 如果有查询条件就会生成where, 如果没有查询条件就不会生成where更新的时候也会出现问题, 使用 <set>
标签来解决
set标签和where标签差不多
<update id="testUpdate">
update user
<set>
<if test="username != null">
username=#{username},
</if>
<if test="password != null">
password=#{password},
</if>
</set>
where userId=#{userId}
</update>
<foreach>
标签有如下属性:
<delete id="testDe">
delete from user where userId in
<foreach collection="list" item="item" open="(" close=")" separator=",">
#{item}
</foreach>
</delete>
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://wangzhi430.blog.csdn.net/article/details/125137029
内容来源于网络,如有侵权,请联系作者删除!