【开发】MyBatis初识
【开发】MyBatis初识
Maven构建
用Maven构建的其中一个重要因素是可以用坐标轻松地导入依赖:
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.19</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>9.6.0</version>
</dependency>
</dependencies>
另外是Maven封装好了各种开发时需要的操作:编译、打包、调试等
初入门
先是根据官网的入门指引一步步做了个demo
引入依赖之后,写一个mybatis-config.xml,根据模板修改
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/jdbc?useSSL=false&allowPublicKeyRetrieval=true"/>
<property name="username" value="role"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="UserMapper.xml"/>
</mappers>
</configuration>
其中需要把allowPublicKeyRetrival设置为true(如果useSSL=false)的话
接着UserMapper.xml处就可以写映射的语句
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="test">
<select id="selectStudent" resultType="com.Student">
SELECT * FROM student
</select>
</mapper>
id就是函数识别映射语句的字符串,resultType是最终返回的内容
回到Student类
package com;
import java.math.BigDecimal;
public class Student {
String name;
String gender;
int age;
BigDecimal score;
String city;
public Student() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public BigDecimal getScore() {
return score;
}
public void setScore(BigDecimal score) {
this.score = score;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Override
public String toString() {
return "=====================\n" +
"名字:" + name + "\n" +
"性别:" + gender + "\n" +
"年龄:" + age + "\n" +
"分数:" + score + "\n" +
"城市:" + city + "\n" +
"======================\n";
}
}
一开始我用的是构造函数,然后运行时报错。看了报错信息发现赋值的顺序似乎并不是确定的,因此可能会有类型错误的问题。所以把构造改成setter,就能保证精准赋值了。
最后是测试代码:
import com.Student;
import org.apache.ibatis.io.*;
import org.apache.ibatis.session.*;
import java.io.*;
import java.util.List;
public class MyBatisDemo {
public static void main(String[] args) throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
List<Student> student = sqlSession.selectList("test.selectStudent");
for (Student stu : student) {
System.out.println(stu);
}
sqlSession.close();
}
}
Mapper代理开发
事实上官方更加建议把接口封装成一个mapper类,通过mapper去映射指令,这样不仅语义好,而且便于编译器识别拼写问题
明确一下流程:
- 定义与SQL映射文件同名的Mapper接口,并且将Mapper接口与映射文件放在同一目录下;
- 设置SQL映射文件的namespace属性为Mapper接口全限定名;
- 在Mapper接口中定义方法,方法名就是SQL映射文件中sql语句的id,并保持参数类型和返回值类型一致;
- 编码:
- 通过SqlSession的getMapper方法获取Mapper接口的代理对象;
- 调用对应方法完成sql的执行。
先是把配置文件和类分别放在resources和java的相同包名下,注意resources处需要用/而不能用.来分割包
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mapper.UserMapper">
<select id="selectStudent" resultType="com.Student">
SELECT * FROM student
</select>
</mapper>
package com.mapper;
import com.Student;
import java.util.List;
public interface UserMapper {
List<Student> selectStudent();
}
在mybatis-config.xml处也要增加一下mapper路径,有两种形式:
<mapper resource="com/mapper/UserMapper.xml"/>
<mapper class = "com.mapper.UserMapper"/>
第一种是资源文件的导入方式,只能识别路径,而另一种是类文件的导入方式,可以识别类,两者选择一个都能使用
最后把本来selectList("")的部分修改成Mapper的形式即可
import com.Student;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import com.mapper.UserMapper;
public class MyBatisDemoMapper {
public static void main(String[] args) throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<Student> student = mapper.selectStudent();
for (Student stu : student) {
System.out.println(stu);
}
sqlSession.close();
}
}
配置文件初步解释
环境配置(environmets)
MyBatis可以配置成适应多种环境,这种机制有助于将SQL映射与多种数据库中。
注意的地方是每个数据库都要对应一个SqlSession实例
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/jdbc?useSSL=false&allowPublicKeyRetrieval=true"/>
<property name="username" value="role"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
别名(typeAlias)
为了降低冗余书写,可以给一些Java类型设置成缩写名字
<typeAliases>
<typeAlias alias="Author" type="domain.blog.Author"/>
<typeAlias alias="Blog" type="domain.blog.Blog"/>
<typeAlias alias="Comment" type="domain.blog.Comment"/>
<typeAlias alias="Post" type="domain.blog.Post"/>
<typeAlias alias="Section" type="domain.blog.Section"/>
<typeAlias alias="Tag" type="domain.blog.Tag"/>
</typeAliases>
别名是不区分大小写的,因此给内置类型用了比较特殊的命名风格,如果是小写开头就在前面加下划线,如果是大写开头就改成小写,自己创建的类也尽量使用小写别名
映射器(Mappers)
这一块上一部分有细讲,就是告诉MyBatis去什么地方找配置文件
功能-查询
查询所有数据
先前写的就是查询所有数据,不多赘述。
不过在这里有一个小问题,由于命名风格的问题,SQL的字段命名和Java的变量命名可能不一样,比如userName和user_name。这个时候如果不加修饰的话,编译过程中是无法识别对应字段进行赋值的。
有两种解决方法:
- 给字段起别名
SELECT user_name as UserName FROM my_table;
不过问题是每个查询都要起一个别名,所以可以抽取重复片段
在xml文件中写:
<sql id = "student_column">
student_name as studentName
</sql>
<mapper namespace="com.mapper.UserMapper">
<select id="selectStudent" resultType="com.Student">
SELECT
<include refid = "student_colmn"/>
FROM student;
</select>
</mapper>
可是这样依旧是硬编码的,假如需要更灵活地查询,这样操作还是比较麻烦
- resultMap
这也是个映射的方法,就可以简单地去把字段映射到变量名
<resultMap id = "studentResultMap" type = "Student">
<result column = "student_name" property = "studentName"/>
<result column = "student_score" property = "studentScore"/>
<!-- 如果是主键的映射,则result改成id -->
</resultMap>
这样写的话,原本resultType的区域就得改成:
<select id = "selectStudent" resultMap = "studentResultMap">
SELECT * FROM student;
</select>
查看详情
有时候会需要一些特定行的详情,在JDBC中用PreparedStatement就是通过setT(id, content)去传入参数的,而在配置文件中也差不多,只不过需要特别的表示方式
<select id="selectById" resultType="com.Student">
SELECT * FROM student WHERE id = #{id};
</select>
而对应声明的地方可以写成:
Student selectById(int id);
使用的时候就简单了:
import com.Student;
import com.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
public class MyBatisSelectById {
public static void main(String[] args) throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Student student = mapper.selectById(3);
System.out.println(student);
sqlSession.close();
}
}
其中符号表示有两种:
- #{}:会被替换成?,避免SQL注入
- ${}:是sql拼接,容易有SQL注入,不过一般会在表名、列名不固定时使用
查询中其实会有一些特殊符号无法直接使用(小于号等),有两种处理方式:
- 转义字符:
SELECT * FROM student WHERE id < 3;
这种方式在特殊字符较少的时候使用
- CDATA区,在CDATA区中就不会被特殊编译了:
<select id="selectById" resultType="com.Student">
<![CDATA[
SELECT * FROM student WHERE id = #{id};
]]>
</select>
条件查询
条件查询有三种方式,共用同一种接口:
<select id="selectByCondition" resultType="com.Student">
SELECT * FROM student
WHERE
name LIKE #{name}
AND gender LIKE #{gender}
AND city LIKE #{city};
</select>
- 传入对象:
定义:
List<Student> selectByCondition(Student student);
使用:
public class MyBatisSelectByConditionClass {
public static void main(String[] args) throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Student stu = new Student();
stu.setName("王五");
stu.setGender("男");
stu.setCity("佛山");
List<Student> student = mapper.selectByCondition(stu);
System.out.println(student);
sqlSession.close();
}
}
- 散装数据加注解
List<Student> selectByCondition(@Param("name") String name,
@Param("gender") String gender,
@Param("city") String city);
其中注解里面的字符串需要与xml对应
public class MyBatisSelectByConditionAnnotation {
public static void main(String[] args) throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<Student> student = mapper.selectByCondition("王五", "男", "佛山");
System.out.println(student);
sqlSession.close();
}
}
- 传入键值对
List<Student> selectByCondition(Map map);
接着就可以分别把字段名和值作为键值对放进去,再查询
public class MyBatisSelectByConditionMap {
public static void main(String[] args) throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Map stu = new HashMap();
stu.put("name", "王五");
stu.put("gender", "男");
stu.put("city", "佛山");
List<Student> student = mapper.selectByCondition(stu);
System.out.println(student);
sqlSession.close();
}
}
动态SQL查询
前面的表字段名有点太简单了,我让GPT生成了一张字段名含下划线,比较复杂的表
CREATE TABLE library_borrow_record (
id INT PRIMARY KEY AUTO_INCREMENT COMMENT '主键',
reader_name VARCHAR(50) NOT NULL COMMENT '借阅人姓名',
book_title VARCHAR(100) NOT NULL COMMENT '书名',
borrow_date DATE NOT NULL COMMENT '借书日期',
due_date DATE NOT NULL COMMENT '应还日期',
return_date DATE COMMENT '实际归还日期',
borrow_status VARCHAR(20) NOT NULL COMMENT '借阅状态',
fine_amount DECIMAL(8,2) DEFAULT 0.00 COMMENT '罚金金额',
shelf_code VARCHAR(30) COMMENT '书架编号',
operator_name VARCHAR(50) COMMENT '办理人姓名',
renew_count INT DEFAULT 0 COMMENT '续借次数',
is_damaged TINYINT DEFAULT 0 COMMENT '是否损坏:0否1是',
remark_text VARCHAR(200) COMMENT '备注信息'
);
INSERT INTO library_borrow_record
(reader_name, book_title, borrow_date, due_date, return_date, borrow_status, fine_amount, shelf_code, operator_name, renew_count, is_damaged, remark_text)
VALUES
('张明', '三体', '2026-03-01', '2026-03-15', '2026-03-14', '已归还', 0.00, 'A_01_03', '李管理员', 1, 0, '按时归还'),
('王雨', '人类简史', '2026-03-05', '2026-03-19', NULL, '借阅中', 0.00, 'B_02_07', '赵管理员', 0, 0, '首次借阅'),
('陈可', '解忧杂货店', '2026-02-20', '2026-03-06', '2026-03-10', '已归还', 4.50, 'C_03_02', '李管理员', 2, 0, '逾期四天'),
('刘晨', '百年孤独', '2026-03-08', '2026-03-22', NULL, '借阅中', 0.00, 'D_01_05', '周管理员', 0, 0, '书籍较新'),
('孙婷', '小王子', '2026-02-25', '2026-03-11', '2026-03-11', '已归还', 0.00, 'A_04_01', '赵管理员', 1, 0, '无'),
('周杰', '活着', '2026-03-02', '2026-03-16', '2026-03-18', '已归还', 3.00, 'B_05_06', '李管理员', 0, 1, '封面轻微破损');
先把对应类写出来:
package com.pojo;
import java.math.BigDecimal;
import java.time.LocalDate;
public class LibraryBorrowRecord {
private Integer id;
private String readerName;
private String bookTitle;
private LocalDate borrowDate;
private LocalDate dueDate;
private LocalDate returnDate;
private String borrowStatus;
private BigDecimal fineAmount;
private String shelfCode;
private String operatorName;
private Integer renewCount;
private Integer isDamaged;
private String remarkText;
public void setId(Integer id) { this.id = id; }
public void setReaderName(String readerName) { this.readerName = readerName; }
public void setBookTitle(String bookTitle) { this.bookTitle = bookTitle; }
public void setBorrowDate(LocalDate borrowDate) { this.borrowDate = borrowDate; }
public void setDueDate(LocalDate dueDate) { this.dueDate = dueDate; }
public void setReturnDate(LocalDate returnDate) { this.returnDate = returnDate; }
public void setBorrowStatus(String borrowStatus) { this.borrowStatus = borrowStatus; }
public void setFineAmount(BigDecimal fineAmount) { this.fineAmount = fineAmount; }
public void setShelfCode(String shelfCode) { this.shelfCode = shelfCode; }
public void setOperatorName(String operatorName) { this.operatorName = operatorName; }
public void setRenewCount(Integer renewCount) { this.renewCount = renewCount; }
public void setIsDamaged(Integer isDamaged) { this.isDamaged = isDamaged; }
public void setRemarkText(String remarkText) { this.remarkText = remarkText; }
public Integer getId() { return id; }
public String getReaderName() { return readerName; }
public String getBookTitle() { return bookTitle; }
public LocalDate getBorrowDate() { return borrowDate; }
public LocalDate getDueDate() { return dueDate; }
public LocalDate getReturnDate() { return returnDate; }
public String getBorrowStatus() { return borrowStatus; }
public BigDecimal getFineAmount() { return fineAmount; }
public String getShelfCode() { return shelfCode; }
public String getOperatorName() { return operatorName; }
public Integer getRenewCount() { return renewCount; }
public Integer getIsDamaged() { return isDamaged; }
public String getRemarkText() { return remarkText; }
@Override
public String toString() {
return "LibraryBorrowRecord{" +
"id=" + id +
", readerName='" + readerName + '\'' +
", bookTitle='" + bookTitle + '\'' +
", borrowDate=" + borrowDate +
", dueDate=" + dueDate +
", returnDate=" + returnDate +
", borrowStatus='" + borrowStatus + '\'' +
", fineAmount=" + fineAmount +
", shelfCode='" + shelfCode + '\'' +
", operatorName='" + operatorName + '\'' +
", renewCount=" + renewCount +
", isDamaged=" + isDamaged +
", remarkText='" + remarkText + '\'' +
'}';
}
}
接着去写配置文件中的映射:
<resultMap id = "RecordMap" type = "com.pojo.LibraryBorrowRecord">
<id column = "id" property = "id"/>
<result column = "reader_name" property = "readerName"/>
<result column = "book_title" property = "bookTitle"/>
<result column = "borrow_date" property = "borrowDate"/>
<result column = "due_date" property = "dueDate"/>
<result column = "return_date" property = "returnDate"/>
<result column = "borrow_status" property = "borrowStatus"/>
<result column = "fine_amount" property = "fineAmount"/>
<result column = "shelf_code" property = "shelfCode"/>
<result column = "operator_name" property = "operatorName"/>
<result column = "renew_count" property = "renewCount"/>
<result column = "is_damaged" property = "isDamaged"/>
<result column = "remark_text" property = "remarkText"/>
</resultMap>
中途我犯了个错误,type区域需要的是实体类而非对应Mapper类
接下来进行动态SQL的说明
在用户的SQL查询中,包含的条件不一定每一项都存在,这个时候需要根据用户给的条件去动态地生成SQL语句
而MyBatis提供了一些标签便于进行这样的操作:
- if
- choose(when, otherwise)
- trim(where, set)
- foreach
if标签
首先看if的用法,在test里面写上条件即可
<select id="selectByCondition" resultMap="RecordMap">
SELECT * FROM library_borrow_record
WHERE
<if test="readerName != null">
reader_name like #{readerName}
</if>
<if test="bookTitle != null and bookTitle != '' ">
and book_title like #{bookTitle}
</if>
<if test="operatorName != null and operatorName != '' ">
and operator_name like #{operatorName}
</if>
</select>
可是这会有一个问题,假如没有给readerName的话,and打头的条件显然是报错的
因此处理方法是在最开始加上一个恒等式,这样就可以让每个条件都独立存在
<select id="selectByCondition" resultMap="RecordMap">
SELECT * FROM library_borrow_record
WHERE 1 = 1
<if test="readerName != null">
and reader_name like #{readerName}
</if>
<if test="bookTitle != null and bookTitle != '' ">
and book_title like #{bookTitle}
</if>
<if test="operatorName != null and operatorName != '' ">
and operator_name like #{operatorName}
</if>
</select>
不过MyBatis其实提供了一个where标签,可以自动检查是否为第一个,进而自己去掉and
<select id="selectByCondition" resultMap="RecordMap">
SELECT * FROM library_borrow_record
<where>
<if test="readerName != null">
and reader_name like #{readerName}
</if>
<if test="bookTitle != null and bookTitle != '' ">
and book_title like #{bookTitle}
</if>
<if test="operatorName != null and operatorName != '' ">
and operator_name like #{operatorName}
</if>
</where>
</select>
choose标签
类似switch语句,只会选择其中一个查询,如果有多个存在,那优先级会取决于配置文件中的顺序
<select id="selectBySingleCondition" resultMap="RecordMap">
SELECT * FROM library_borrow_record WHERE
<choose>
<when test="readerName != null">
reader_name like #{readerName}
</when>
<when test="bookTitle != null and bookTitle != '' ">
book_title like #{bookTitle}
</when>
<when test="operatorName != null and operatorName != '' ">
operator_name like #{operatorName}
</when>
<otherwise>
1 = 1
</otherwise>
</choose>
</select>
不用otherwise标签的话,如果直接这样,在没有任何条件的时候就会报错,这个时候可以将WHERE改成where标签,这样效果就与原先的otherwise一致了
功能-修改与添加
添加行
- 普通添加
先是添加一个接口函数:
public void addRecord(LibraryBorrowRecord record);
静态的没有什么特别大的问题,主要注意拼写
<insert id="addRecord">
INSERT INTO library_borrow_record
( reader_name, book_title, borrow_date, due_date, return_date, borrow_status, fine_amount,
shelf_code, operator_name, renew_count, is_damaged, remark_text )
VALUES
( #{readerName}, #{bookTitle}, #{borrowDate}, #{dueDate},
#{returnDate}, #{borrowStatus}, #{fineAmount},
#{shelfCode}, #{operatorName}, #{renewCount},
#{isDamaged}, #{remarkText});
</insert>
然后在sqlSession中,对于这种修改操作,需要自行设置是否自动提交
如果不自动提交,在事务结束之后需要
sqlSession.commit();
如果设置自动提交的话
public class AddColumn {
public static void main(String[] args) throws IOException {
String resources = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resources);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//在此处参数填上true代表自动提交,默认不自动
SqlSession sqlSession = sqlSessionFactory.openSession(true);
LibraryBorrowRecordMapper mapper = sqlSession.getMapper(LibraryBorrowRecordMapper.class);
LibraryBorrowRecord record = new LibraryBorrowRecord();
/*
此处setter过程省略
*/
mapper.addRecord(record);
}
}
- 主键返回
有时候添加操作之后是需要获取插入的主键的值的,比如购物平台上添加订单的订单项时,订单项中需要获取订单id
操作很简单,在原先添加行的位置修改为:
<insert id="addRecord" useGeneratedKeys="true" keyProperty="id">
这样就能让对象的id被赋值了
对于前面的代码,在最后输出record.setId(),前后对比可以得知主键返回的作用
修改
- 修改全部字段
这里全都是静态的,因此就不多写了
- 修改动态字段
这一功能可以涵盖上一个功能,所以重点讲这个
接口函数:
public void updateRecord(LibraryBorrowRecord record);
可以想到类似于动态查询的问题,如果某个字段要被修改并且它是最后一个,那么正常来讲带着逗号的话肯定无法过编译
所以MyBatis提供了set标签解决了这个问题
<update id="updateRecord">
UPDATE library_borrow_record
<set>
<if test="readerName != null and readerName != '' ">
reader_name = #{readerName},
</if>
<if test="bookTitle != null and bookTitle != '' ">
book_title = #{bookTitle},
</if>
<if test="remarkText != null and remarkText != '' ">
remark_text = #{remarkText},
</if>
</set>
where id = #{id}
</update>
public class UpdateColumn {
public static void main(String[] args) throws IOException {
String resources = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resources);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
LibraryBorrowRecordMapper mapper = sqlSession.getMapper(LibraryBorrowRecordMapper.class);
LibraryBorrowRecord record = new LibraryBorrowRecord();
record.setId(8);
record.setReaderName("嘉琪");
record.setRemarkText("轻微破损痕迹");
mapper.updateRecord(record);
}
}
功能-删除
删除一个
这就简单了
public void deleteById(int id);
<delete id="deleteById">
DELETE FROM library_borrow_record WHERE id = #{id};
</delete>
批量删除
对于“批量”来讲,一组数据的长度是不定的,也就是说不能硬编码删除的数量
所以MyBatis提供了foreach标签去完成变长数据的处理
public void deleteByIds(@Param("ids") int[] ids);
<delete id="deleteByIds">
DELETE FROM library_borrow_record
WHERE id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
讲解一下其中的foreach部分,可以看出这其实是生成了一个字符串
collection代表的是标签名,在这个例子中,需要用@Param注解将原先的变量名用ids表示用于识别
MyBatis会将数组参数封装成一个Map集合,默认key是array,而值就是数组,可以通过@Param注解改变默认key的别名
item就是单个元素对应的字段名
seperator和open、close都是用来生成语句的
参数传递
前面提到过可以散装传入参数,但是需要用@Param注解
因为MyBatis会将多个参数封装成Map,它自身会有默认键arg0,arg1,.……和param1,param2,……
因此可以通过使用这两种键去在xml中调用参数
但是这样明显语义不是很好,所以@Param["str"]就可以起名字,这样就会有这样的变成:
map.put("str", value);
就结论而言,POJO类型和Map类型不需要另加注解,而Collection、List、Array和多参数都需要注解,这样才便于开发
注解开发
xml文件配置其实比较复杂,如果不去做比较复杂的事务的话,可以考虑直接用提供的注解,MyBatis给了以下几种注解
- @Select
- @Insert
- @Update
- @Delete
具体例子如下:
@Select("SELECT * FROM users WHERE id = #{id}")
public User selectById(int id);

浙公网安备 33010602011771号