提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
增 删 改 的返回数据类型都是int
一、select查询
1、带参数查询
编写接口
com.lihaozhe.mapper.PersonMapper
参数只有一个时,@Param(“文件名”)可以不写,这是映射文件读取的文件名
package com.lihaozhe.mapper;
import com.lihaozhe.pojo.Person;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @author
* @version 1.0.0 2022/7/6 上午8:52
*/
public interface PersonMapper {
/**
* 根据手机号查询用户信息
* @param mobile
* @return
* 参数只有一个@Param("Mobile")可以不写,这是映射文件读取的文件名,生成映射文件
*/
Person selectByMobile(@Param("mobile") String mobile);
}
编写映射配置文件
src/main/resources/com/lihaozhe/mapper/PersonMapper.xml
默认情况下,使用 #{} 参数语法时,MyBatis 会创建 PreparedStatement 参数占位符,并通过占位符安全地设置参数(就像使用 ? 一样)。
<?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.lihaozhe.mapper.PersonMapper">
<!--根据手机号查询用户信息-->
<select id="selectByMobile" parameterType="java.lang.String" resultType="com.lihaozhe.pojo.Person">
SELECT *
FROM `person`
WHERE `mobile` = #{mobile}
</select>
</mapper>
这里映射配置文件里的sql语句读取到接口内的参数
测试类
com.lihaozhe.mapper.PersonMapperTest
注意:测试方法中获取SqlSession对象
@Test
public void selectByMobile(){
// 获取该接口的代理对象
PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
// 执行接口中的方法
Person person = mapper.selectByMobile("13925135946");
// 释放SqlSession资源
sqlSession.close();
// 输出查询结果
System.out.println(person);
}
2、#与$的区别
默认情况下,使用 #{} 参数语法时,MyBatis 会创建 PreparedStatement 参数占位符,并通过占位符安全地设置参数(就像使用 ? 一样)。
这样做更安全,更迅速,通常也是首选做法,不过有时你就是想直接在 SQL 语句中直接插入一个不转义的字符串。
比如 ORDER BY 子句,MyBatis 就不会修改或转义该字符串了。
#{} 会进行预编译,比较安全
${} 直译,获取值使直接
需求:查询的条件字段和该字段的值不确定时,需要通过查询字段在查询值
编写接口
com.lihaozhe.mapper.PersonMapper
package com.lihaozhe.mapper;
import com.lihaozhe.pojo.Person;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @author 李昊哲
* @version 1.0.0 2022/7/6 上午8:52
*/
public interface PersonMapper {
/**
* 根据不确定的字段查询
* @param column 输入的参数是指字段名
* @param value 输入的参数是指数据值
* @return
*/
Person selectByFiled(@Param("column") String column,@Param("value")String value);
}
编写映射配置文件
src/main/resources/com/lihaozhe/mapper/PersonMapper.xml
这里注意
${}是直译,直接是参数值
#{}会预编译,编译完后有sql语句的参数有‘ 单引号 ’
<?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.lihaozhe.mapper.PersonMapper">
<!--根据不确定的字段查询-->
<select id="selectByFiled" resultType="com.lihaozhe.pojo.Person">
SELECT *
FROM `person`
WHERE ${column} = #{value}
</select>
</mapper>
测试
@Test
public void selectByFiled() {
// 获取该接口的代理对象
PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
// 执行接口中的方法
Person person = mapper.selectByFiled("mobile","17778322703");
// 释放SqlSession资源
sqlSession.close();
// 遍历集合
System.out.println(person);
}
}
3、别名映射
别名映射修改的是映射文件中类的的路径名
在核心配置文件中将类的路径名指定一个别名
有2种方法
1、为某个类指定别名
2、为某个包下的所有类指定别名 别名默认是这个类的首字母小写之后的字符串
起因:parameterType 和 resultType 的值 需要使用类的完全限定名 太麻烦 希望使用 简短的名字来替代 类的完全限定名
在核心配置文件中 配置如下内容:
<typeAliases>
<!--
别名
type 类的完全限定名
alias 别名
-->
<!--1、为某个类指定别名-->
<!--<typeAlias alias="login" type="com.lihaozhe.pojo.Login"/>-->
<!--2、为某个包下的所有类指定别名 别名默认为类的首字母小写之后的字符串-->
<package name="com.lihaozhe.pojo"/>
</typeAliases>
编写接口
com.lihaozhe.mapper.PersonMapper
package com.lihaozhe.mapper;
import com.lihaozhe.pojo.Login;
import org.apache.ibatis.annotations.Param;
/**
* @author 李昊哲
* @version 1.0.0 2022/7/7 上午8:52
*/
public interface PersonMapper {
/**
* 根据唯一身份标识符用户信息
*
* @param uuid
* @return
*/
Person selectByUuid(@Param("uuid") String uuid);;
}
编写映射配置文件
src/main/resources/com/lihaozhe/mapper/PersonMapper.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.lihaozhe.mapper.PersonMapper">
<!--根据唯一身份标识符用户信息-->
<select id="selectByUuid" resultType="person">
SELECT *
FROM `person`
WHERE uuid = #{uuid}
</select>
</mapper>
测试类
com.lihaozhe.mapper.PersonMapperTest
注意:测试方法中获取SqlSession对象
@Test
public void selectByuuid() {
// 获取该接口的代理对象
PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
// 执行接口中的方法
Person person = mapper.selectByuuid("uuid","2b6e912a2e56485ea4233eca400c38ab");
// 释放SqlSession资源
sqlSession.close();
// 遍历集合
System.out.println(person);
}
完整核心配置文件
src/main/resources/mybatis/myatis-confog.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--
这些属性可以在外部进行配置,并可以进行动态替换。
你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置
-->
<properties resource="config.properties" />
<settings>
<!-- 驼峰命名与下划线自动转换 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- log日志 -->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<typeAliases>
<!--
别名
type 类的完全限定名
alias 别名
-->
<!--为某个类指定别名-->
<!--<typeAlias alias="person" type="com.lihaozhe.pojo.Person"/>-->
<!--为某个包下的所有类指定别名 别名默认为类的首字母小写之后的字符串-->
<package name="com.lihaozhe.pojo"/>
</typeAliases>
<!--
MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中, 现实情况下有多种理由需要这么做。
例如,开发、测试和生产环境需要有不同的配置;或者想在具有相同 Schema 的多个生产数据库中使用相同的 SQL 映射。还有许多类似的使用场景。
-->
<!--默认使用的环境 ID(比如:default="development")。-->
<environments default="development">
<!--每个 environment 元素定义的环境 ID(比如:id="development")。-->
<environment id="development">
<!--事务管理器的配置(比如:type="JDBC")。-->
<!--
事务管理器(transactionManager)
在 MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]"):
JDBC – 这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。
MANAGED – 这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。
默认情况下它会关闭连接。然而一些容器并不希望连接被关闭,因此需要将 closeConnection 属性设置为 false 来阻止默认的关闭行为。
如果你正在使用 Spring + MyBatis,则没有必要配置事务管理器,因为 Spring 模块会使用自带的管理器来覆盖前面的配置。
这两种事务管理器类型都不需要设置任何属性。它们其实是类型别名,换句话说,你可以用 TransactionFactory 接口实现类的全限定名或类型别名代替它们。
-->
<transactionManager type="JDBC"/>
<!--数据源的配置(比如:type="POOLED")-->
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 使用相对于类路径的资源引用 -->
<!--单独加载某个映射配置文件-->
<!--<mapper resource="mybatis/mapper/PersonMapper.xml"/>-->
<!-- 使用完全限定资源定位符(URL) -->
<!--<mapper url="file:///home/lhz/mybatis/src/main/resources/com/lihaozhe/mapper/PersonMapper.xml"/>-->
<!--<mapper url="file:///D:/mybatis/src/main/resources/com/lihaozhe/mapper/PersonMapper.xml"/>-->
<!--加载某包下所有的映射配置文件-->
<package name="com.lihaozhe.mapper"/>
</mappers>
</configuration>
二、insert新增
首先生成pojo类,封装,构造方法
编写接口
com.lihaozhe.mapper.DeptMapper
增删改的返回值都是int类型,是行数的变动
package com.lihaozhe.mapper;
import com.lihaozhe.pojo.Dept;
import org.apache.ibatis.annotations.Param;
/**
* @author 李昊哲
* @version 1.0.0 2022/7/6 上午8:52
*/
public interface DeptMapper {
/**
* 新增部门
*
* @param dept
* @return
*/
int insert(@Param("dept") Dept dept);
}
编写映射配置文件
src/main/resources/com/lihaozhe/mapper/DeptMapper.xml
新增数据中的新增占位 #{dept.dname}是指 某表下的字段
<?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.lihaozhe.mapper.DeptMapper">
<!--新增部门-->
<insert id="insert">
INSERT INTO `dept` (`dname`)
VALUES (#{dept.dname})
</insert>
</mapper>
测试类
com.lihaozhe.mapper.DeptMapperTest
注意:测试方法中获取SqlSession对象
package com.lihaozhe.mapper;
import com.lihaozhe.pojo.Dept;
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 org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.io.Reader;
/**
* @author 李昊哲
* @version 1.0.0 2022/7/6 上午8:52
*/
public class DeptMapperTest {
private SqlSession sqlSession;
// JUnit5 @BeforeAll和@BeforeEach注解替换了 JUnit4 中的@Before注解。
// 它⽤于表⽰应在当前类中的每个@Test⽅法之前执⾏注解⽅法。
// 注意:@BeforeAll注解的⽅法必须为静态⽅法,否则它将引发运⾏时错误。
// 注意:@BeforeEach注解的⽅法不得为静态⽅法,否则它将引发运⾏时错误。
@BeforeEach
public void openSqlSession() throws IOException {
// 核心配置文件classpath路径
String resource = "mybatis/mybatis-config.xml";
// 加载配置文件
Reader reader = Resources.getResourceAsReader(resource);
// 构建会话工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
// 从SqlSessionFactory对象中获取SqlSession
sqlSession = sqlSessionFactory.openSession();
}
@Test
public void insert(){
// 获取代理对象
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
// 准备数据
Dept dept = new Dept("人事部");
// 插入之前 输出准备数据
System.out.println("插入之前 dept >>> " + dept);
// 调用方法执行 insert 操作
mapper.insert(dept);
// 手动提交事务
sqlSession.commit();
// 释放资源
sqlSession.close();
// 插入之后 输出准备数据
System.out.println("插入之后 dept >>> " + dept);
}
}
新增数据主键并没有自增需要在映射文件中配置
解析结果:
插入之前 dept >>> Dept(did=0, dname=人事部)
Opening JDBC Connection
Created connection 671596011.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@2807bdeb]
==> Preparing: INSERT INTO `dept` (`dname`) VALUES (?)
==> Parameters: 人事部(String)
<== Updates: 1
Committing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@2807bdeb]
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@2807bdeb]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@2807bdeb]
Returned connection 671596011 to pool.
插入之后 dept >>> Dept(did=0, dname=人事部)
新增数据后如何获取新增数据主键值
新增时,需要自己指定主键 自增
<?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.lihaozhe.mapper.DeptMapper">
<!--新增部门-->
<!--
useGeneratedKeys参数默认是false,
在进行insert操作后是获取不到自增的id的,
如果我们需要用到主键需要将参数值改为true
keyProperty javabean 中主键 filed
keyColumn datatable 中主键 filed
-->
<insert id="insert" useGeneratedKeys="true" keyProperty="did" keyColumn="did">
INSERT INTO `dept` (`dname`)
VALUES (#{dept.dname})
</insert>
</mapper>
三、update修改
编写接口
com.lihaozhe.mapper.DeptMappe
根据部门主键修改,传一个值返回一个对象
package com.lihaozhe.mapper;
import cn.hutool.core.collection.LineIter;
import com.lihaozhe.pojo.Dept;
import org.apache.ibatis.annotations.Param;
/**
* @author 李昊哲
* @version 1.0.0 2022/7/6 上午8:52
*/
public interface DeptMapper {
/**
* 修改部门信息
*
* @param dept
* @return
*/
int update(@Param("dept") Dept dept);
}
编写映射配置文件
src/main/resources/com/lihaozhe/mapper/DeptMapper.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.lihaozhe.mapper.DeptMapper">
<!--修改部门信息 dname中是要更新的部门,条件是did 传入一个表的id-->
<update id="update">
UPDATE `dept`
SET `dname` = #{dept.dname}
WHERE `did` = #{dept.did}
</update>
</mapper>
测试类
com.lihaozhe.mapper.DeptMappeTest
package com.lihaozhe.mapper;
import com.lihaozhe.pojo.Dept;
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 org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.io.Reader;
/**
* @author 李昊哲
* @version 1.0.0 2022/7/6 上午8:52
*/
public class DeptMapperTest {
private SqlSession sqlSession;
// JUnit5 @BeforeAll和@BeforeEach注解替换了 JUnit4 中的@Before注解。
// 它⽤于表⽰应在当前类中的每个@Test⽅法之前执⾏注解⽅法。
// 注意:@BeforeAll注解的⽅法必须为静态⽅法,否则它将引发运⾏时错误。
// 注意:@BeforeEach注解的⽅法不得为静态⽅法,否则它将引发运⾏时错误。
@BeforeEach
public void getSqlSession() throws IOException {
// 核心配置文件classpath路径
String resource = "mybatis/mybatis-config.xml";
// 加载配置文件
Reader reader = Resources.getResourceAsReader(resource);
// 构建会话工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
// 从SqlSessionFactory对象中获取SqlSession
sqlSession = sqlSessionFactory.openSession();
}
@Test
public void update() {
// 获取代理对象
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
// 准备数据
Dept dept = new Dept(8, "企宣部");
// 调用方法执行 update 操作
mapper.update(dept);
// 手动提交事务
sqlSession.commit();
// 释放资源
sqlSession.close();
}
}
四、delete删除
编写接口
com.lihaozhe.mapper.DeptMappe
根据部门主键删除,传一个id完成删除所以是long基本类型
package com.lihaozhe.mapper;
import cn.hutool.core.collection.LineIter;
import com.lihaozhe.pojo.Dept;
import org.apache.ibatis.annotations.Param;
/**
* @author 李昊哲
* @version 1.0.0 2022/7/6 上午11:13
*/
public interface DeptMapper {
/**
* 根据部门id删除部门
*
* @param did
* @return
*/
int deleteByDid(@Param("did") long did);
}
编写映射配置文件
src/main/resources/com/lihaozhe/mapper/DeptMapper.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.lihaozhe.mapper.DeptMapper">
<!--根据部门id删除部门-->
<delete id="deleteByDid">
DELETE
FROM `dept`
WHERE `did` = #{did}
</delete>
</mapper>
测试类
com.lihaozhe.mapper.DeptMappeTest
package com.lihaozhe.mapper;
import com.lihaozhe.pojo.Dept;
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 org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.io.Reader;
/**
* @author 李昊哲
* @version 1.0.0 2022/7/7 下午3:56
*/
public class DeptMapperTest {
private SqlSession sqlSession;
// JUnit5 @BeforeAll和@BeforeEach注解替换了 JUnit4 中的@Before注解。
// 它⽤于表⽰应在当前类中的每个@Test⽅法之前执⾏注解⽅法。
// 注意:@BeforeAll注解的⽅法必须为静态⽅法,否则它将引发运⾏时错误。
// 注意:@BeforeEach注解的⽅法不得为静态⽅法,否则它将引发运⾏时错误。
@BeforeEach
public void getSqlSession() throws IOException {
// 核心配置文件classpath路径
String resource = "mybatis/mybatis-config.xml";
// 加载配置文件
Reader reader = Resources.getResourceAsReader(resource);
// 构建会话工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
// 从SqlSessionFactory对象中获取SqlSession
sqlSession = sqlSessionFactory.openSession();
}
@Test
public void deleteByDid(){
// 获取代理对象
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
// 调用方法执行 delete 操作
mapper.deleteByDid(8);
// 手动提交事务
sqlSession.commit();
// 释放资源
sqlSession.close();
}
}
五、工具类
com.lihaozhe.util.mybatis.MyBatisUtil
package com.lihaozhe.util.mybatis;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.ExecutorType;
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.Reader;
/**
* @author 李昊哲
* @version 1.0.0 2022/7/13 上午11:39
*/
public abstract class MyBatisUtil {
private static ThreadLocal<SqlSession> threadLocal = new ThreadLocal<>();
private static SqlSessionFactory sqlSessionFactory;
private static SqlSession sqlSession;
static {
// 核心配置文件classpath路径
String resource = "mybatis/mybatis-config.xml";
// 加载配置文件
Reader reader = null;
try {
reader = Resources.getResourceAsReader(resource);
// 构建会话工厂
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 获取 SqlSession 对象
*
* @return SqlSession 对象
*/
public static SqlSession openSqlSession() {
if (threadLocal.get() == null) {
// 从SqlSessionFactory对象中获取SqlSession
sqlSession = sqlSessionFactory.openSession();
// 与线程绑定
threadLocal.set(sqlSession);
// 返回 SqlSession 对象
return sqlSession;
} else {
return threadLocal.get();
}
}
/**
* 获取 SqlSession 对象
*
* @param executorType SIMPLE,REUSE,BATCH
* @return SqlSession 对象
*/
public static SqlSession openSqlSession(ExecutorType executorType) {
if (threadLocal.get() == null) {
// 从SqlSessionFactory对象中获取SqlSession
sqlSession = sqlSessionFactory.openSession(executorType);
// 与线程绑定
threadLocal.set(sqlSession);
// 返回 SqlSession 对象
return sqlSession;
} else {
return threadLocal.get();
}
}
/**
* 释放资源
*/
public static void close() {
if (threadLocal.get() != null) {
sqlSession = threadLocal.get();
threadLocal.remove();
sqlSession.close();
}
}
/**
* 事务提交 释放资源
*/
public static void commitAndClose() {
if (threadLocal.get() != null) {
sqlSession = threadLocal.get();
threadLocal.remove();
sqlSession.commit();
sqlSession.close();
}
}
/**
* 事务回滚 释放资源
*/
public static void rollbackAndClose() {
if (threadLocal.get() != null) {
sqlSession = threadLocal.get();
threadLocal.remove();
sqlSession.rollback();
sqlSession.close();
}
}
}