一、代理Dao方式的CRUD操作
1. 代理Dao方式的增删改查
1.1 创建项目
沿用(一)的 Maven 项目,确保依赖和配置文件均已就绪
1.2 UserMapper 接口代码
java
package com.qcby.mapper;
import com.qcby.domain.User;
import java.util.List;
public interface UserMapper {
// 查询所有用户
public List<User> findAll();
// 根据ID查询用户
public User findById(Integer userId);
// 插入用户
public void insert(User user);
// 更新用户
public void update(User user);
// 删除用户
public void delete(Integer userId);
// 根据用户名模糊查询
public List<User> findByName(String username);
// 查询总记录数
public Integer findByCount();
}
1.3 UserMapper.xml 映射文件
在 resources/mappers 目录下完善 UserMapper.xml 文件。
java
<?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.qcby.mapper.UserMapper">
<!-- 查询所有 -->
<select id="findAll" resultType="com.qcby.domain.User">
select * from user
</select>
<!-- 根据ID查询 -->
<!-- 使用 #{任意变量名} 接收基本类型参数 -->
<select id="findById" resultType="com.qcby.domain.User" parameterType="int">
select * from user where id = #{id};
</select>
<!-- 保存操作 -->
<insert id="insert" parameterType="com.qcby.domain.User">
<!--
selectKey 用于获取插入数据后生成的主键值
keyProperty: 将查询到的主键值设置到 parameterType 对象的哪个属性
order: 在 INSERT 语句执行前(BEFORE)后(AFTER)执行
resultType: 返回的主键类型
-->
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
select last_insert_id();
</selectKey>
insert into user (username,birthday,sex,address)
values (#{username},#{birthday},#{sex},#{address})
</insert>
<!-- 修改操作 -->
<update id="update" parameterType="com.qcby.domain.User">
update user
set username = #{username}, birthday = #{birthday}, sex = #{sex}, address = #{address}
where id = #{id}
</update>
<!-- 删除操作 -->
<delete id="delete" parameterType="Integer">
delete from user where id = #{id}
</delete>
<!-- 模糊查询方式一:推荐,使用 #{...} 拼接,传入参数时需要自己加上 '%' -->
<!--
<select id="findByName" resultType="com.qcby.domain.User" parameterType="string">
select * from user where username like #{username}
</select>
-->
<!-- 模糊查询方式二:不推荐,存在SQL注入风险,使用 ${...} 拼接 -->
<!-- 注意:参数名必须是 value -->
<select id="findByName" resultType="com.qcby.domain.User" parameterType="string">
select * from user where username like '%${value}%'
</select>
<!-- 查询总记录数 -->
<select id="findByCount" resultType="int">
select count(*) from user
</select>
</mapper>
1.4 测试类代码
java
package com.qcby.test;
import com.qcby.domain.User;
import com.qcby.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 org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
public class UserTest {
private InputStream in;
private SqlSession session;
private UserMapper mapper;
// 在所有测试方法执行前执行,用于初始化
@Before
public void init() throws Exception {
// 1. 加载主配置文件
in = Resources.getResourceAsStream("SqlMapConfig.xml");
// 2. 创建 SqlSessionFactory 对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
// 3. 获取 SqlSession 对象
session = factory.openSession();
// 4. 获取 Mapper 接口的代理对象
mapper = session.getMapper(UserMapper.class);
}
// 在所有测试方法执行后执行,用于释放资源
@After
public void destroy() throws Exception {
session.close();
in.close();
}
@Test
public void testFindAll() {
List<User> list = mapper.findAll();
for (User user : list) {
System.out.println(user);
}
}
@Test
public void testFindById() {
User user = mapper.findById(1);
System.out.println(user);
}
@Test
public void testInsert() {
User user = new User();
user.setUsername("美美");
user.setBirthday(new Date());
user.setSex("女");
user.setAddress("北京");
mapper.insert(user);
// 插入操作需要手动提交事务
session.commit();
System.out.println("插入后生成的主键ID:" + user.getId());
}
@Test
public void testUpdate() {
User user = mapper.findById(1);
if (user != null) {
user.setUsername("小凤");
mapper.update(user);
session.commit();
}
}
@Test
public void testDelete() {
// 假设删除ID为48的用户
mapper.delete(48);
session.commit();
}
// 模糊查询示例(对应XML中的方式二)
@Test
public void testFindByName() {
List<User> list = mapper.findByName("王");
for (User user : list) {
System.out.println(user);
}
}
@Test
public void testFindByCount() {
Integer count = mapper.findByCount();
System.out.println("总记录数:" + count);
}
}
二、MyBatis 参数详解
1. parameterType(输入参数类型)
parameterType 用于配置 SQL 语句的参数类型。
**简单数据类型:**如 int, double, String, long 等。
-
全限定名:
java.lang.Integer等。 -
别名:MyBatis 提供简写,如
int、integer、Int、Integer都可以。
POJO 对象类型: Java 实体类,如 User。
**POJO 包装对象类型:**当一个实体类无法满足传参需求时,可以定义一个包装类,包含多个实体作为属性。
2. resultType(输出结果类型)
resultType 用于指定 SQL 语句的返回值类型。
返回简单数据类型:如 int, double, long, String 等。
返回 POJO 数据类型: 如 User,要求 SQL 查询的列名和 POJO 的属性名一致。
**resultMap:**当 SQL 查询字段名和 POJO 属性名不一致时,或需要映射复杂类型(如一对一、一对多)时使用。
resultMap 配置示例
假设 SQL 查询使用了别名,导致字段名与 User 属性不一致。
java
<!-- 查询语句中使用了别名 -->
<select id="findUsers" resultMap="userMap">
select id _id, username _username, birthday _birthday, sex _sex, address _address from user
</select>
<!-- 配置 resultMap 建立映射关系 -->
<!--
id: 唯一标识,被 select 标签的 resultMap 引用
type: 最终要映射成的 Java 类型
-->
<resultMap id="userMap" type="com.qcby.domain.User">
<!-- result 标签配置普通属性的映射 -->
<!--
property="JavaBean中的属性"
column="表中的字段"
-->
<result property="id" column="_id"/>
<result property="username" column="_username"/>
<result property="birthday" column="_birthday"/>
<result property="sex" column="_sex"/>
<result property="address" column="_address"/>
</resultMap>