MyBatis是持久层框架(持久层: 和数据库进行交互的代码;框架: 半成品软件模型)。简化了JDBC开发(使用Java提供的标准Api来操作和访问数据库)。
JDBC开发的流程:
对应下面的代码:
// 1. 注册数据库驱动
Class.forName("com.mysql.jdbc.Driver");
// 2. 建立Connection连接
String url = "jdbc:mysql://db1?useSSL=false";
String uname = "root";
String pwd = "1234";
Connection conn = DriverManager.getConnection(url, uname, pwd);
// 3. 设置性别参数为男
String gender = "男";
// 4. 定义SQL查询语句
String sql = "select * from tb_user where gender = ?";
// 5. 创建预处理语句对象
PreparedStatement pstmt = conn.prepareStatement(sql);
// 6. 设置参数值
pstmt.setString(1, gender);
// 7. 执行SQL查询
ResultSet rs = pstmt.executeQuery();
// 8. 创建用户对象和用户列表
User user = null;
ArrayList<User> users = new ArrayList<>();
// 9. 遍历结果集
while (rs.next()) {
// 从结果集中获取数据
int id = rs.getInt("id");
String username = rs.getString("username");
String password = rs.getString("password");
// 创建User对象并设置属性
user = new User();
user.setId(id);
user.setUsername(username);
user.setPassword(password);
user.setGender(gender);
// 将用户对象添加到列表中
users.add(user);
}
硬编码: 配置信息和sql语句写到了代码里,之后如果改动需要改动代码。
操作繁琐: 手动设置sql语句的参数、手动解析结果并封装到对象中。
xml配置文件: 对于硬编码问题,MyBatis使用将配置信息和sql语句都写到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>
<environments default="dev">
<environment id="dev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
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.example.mapper.UserMapper">
<select id="findUserById" parameterType="int" resultType="com.example.model.User">
SELECT id, name, age FROM user WHERE id = #{id}
</select>
</mapper>
对于操作繁琐问题,mybatis只需要一行代码就能把参数设置和封装结果解决完,让这两个操作实现了自动完成。
// 1. 加载MyBatis配置文件,获取SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 2. 获取SqlSession对象,用它来执行sql
SqlSession sqlSession = sqlSessionFactory.openSession();
// 3. 执行sql
List<User> users = sqlSession.selectList(statement: "test.selectAll");
System.out.println(users);
// 4. 释放资源
sqlSession.close();
MyBatis中的SqlSession类似于JDBC中的Connection,但是提供了更高级别的抽象和封装。
通过xml配置文件获取SqlSessionFactory,然后获取SqlSession,也就类似于JDBC中的Connection
上文使用SqlSession来执行sql,还是会存在硬编码的问题,就是我们要知道sql配置文件中对应的sql语句的id叫什么。写起来还是不太方便。所以还可以使用Mapper代理开发,更加方便。
具体细节就不赘述。简单讲一讲实现。
创建一个mapper接口,用来配合mapper.xml文件,这个接口和mapper.xml要放在同一个路径下(spring可以通过更改扫描路径)。mapper.xml中的namespace要是接口的全限定名,并且mapper接口要有一个与mapper.xml对应sql的id相同名的方法,返回值也要和mapper.xml中对应sql的返回值相同。
然后通过SqlSession获取mapper接口的代理对象,使用代理对象直接调用接口的方法就能直接执行sql语句并且获取到对应的返回值了。
起别名: sql语句查询的时候可以通过as给不一致的列表起与实体属性名一致的别名。
resultMap: 定义<resultMap>完成不一致的属性名和列名的映射,然后使用resultMap替换 <select>标签中的resultType。
mapper接口中带参数的方法需要在sql的select语句中搭配一个占位符,而占位符有两种,分别是${}和#{},他们两个是不同的。
${}: 会把参数替换占位符,拼接上原来的sql语句,然后组成一个完整的sql语句去进行sql查询,类似jdbc的Statement做的一样,不会预编译。
#{}: 会进行sql语句的预编译,然后会把参数替换掉预编译的占位符上,可以有效防止sql注入的问题。类似PreparedStatement。
<select>
用于定义查询语句,执行数据库的SELECT
操作,返回结果集。
常用于查询数据,支持动态SQL和映射。
@Param
这是MyBatis的注解,用于给Mapper接口方法的参数命名。
当接口方法有多个参数时,使用@Param("name")
可以在SQL中通过#{name}
引用对应参数。
<set>
用于UPDATE
语句中,动态拼接SET
子句。
会自动处理多余的逗号,避免SQL语法错误。
示例:
xml复制编辑<set>
<if test="name != null">name = #{name},</if>
<if test="age != null">age = #{age},</if>
</set>
<foreach>
用于遍历集合(List、数组、Map等),动态生成SQL片段,常用于批量操作和IN
条件。
示例:
xml复制编辑WHERE id IN
<foreach item="id" collection="idList" open="(" separator="," close=")">
#{id}
</foreach>
<where>
用于动态生成WHERE
子句,会智能处理多余的AND
或OR
。
如果内部没有条件,则不会生成WHERE
关键字。
<insert>
定义插入语句,对应数据库的INSERT
操作。
可以支持动态字段插入。
<delete>
定义删除语句,对应数据库的DELETE
操作。
用于删除符合条件的数据。
<update>
定义更新语句,对应数据库的UPDATE
操作。
常配合<set>
标签使用,动态更新字段。
<choose>
类似Java中的switch-case
,用于多个条件分支中选择一个执行。
包含<when>
和<otherwise>
子标签。
示例:
xml复制编辑<choose>
<when test="type == 'A'">...</when>
<when test="type == 'B'">...</when>
<otherwise>...</otherwise>
</choose>
Mapper接口的方法中可以接收各种参数,可以接收
属性名和参数占位符名称一致。
Map集合键名要和参数占位符一致。
封装为map集合,map.put("collection",Collection集合),map.put("arg0",Collection集合)
封装为map集合,map.put("arg0",List集合),map.put("collection",List集合),map.put("list",List集合)
封装为map集合,map.put("arg0",Array数组), map.put("array", Array数组)
使用多个参数的时候,要使用@Param注解来定义参数的名称,这个名称要和sql语句的参数占位符一致,才能将这个参数替换到占位符上去。
ParamNameResolver封装参数: mapper接口方法如果有多个参数,那么这些参数就会被封装到一个Map集合中,key就是使用@Param定义的名称(没有@Param注解的话,默认就是arg0、arg1...和param0、param1...作为键值,使用@Param注解的话,替换的键名是argx的,paramx还存在),然后值就是参数传递过来的。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。