目录
1. MyBatis 高级查询
1.1 ResultMap 属性
建立对象关系映射
- resultType: 如果实体的属性名与表中字段名一致,将查询结果自动封装到实体类中
- resutlMap:如果实体的属性名与表中字段名不一致,可以使用 resutlMap 实现手动封装到实体类中
编写 UserMapper 接口
List<User> findAllResultMap();
编写 UserMapper.xml
<!-- id: 标签的唯一标识,type: 封装后实体类型 -->
<resultMap id="userResultMap" type="com.zm.domain.User">
<!-- 手动配置映射关系 -->
<!-- id: 用来配置主键 。表中主键字段封装
column="id" :表中的字段名
property="id" :user实体的属性名-->
<id property="id" column="uid"></id>
<!-- result: 表中普通字段的封装 -->
<result property="username" column="NAME"></result>
<result property="birthday" column="birthday"></result>
<result property="sex" column="sex"></result>
<result property="address" column="address"></result>
</resultMap>
<!-- 查询所有用户 -->
<select id="findAllResultMap" resultMap="userResultMap">
select * from `user`
</select>
代码测试
@Before
public void init() throws IOException {
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("sqlMapConfig.xml"));
sqlSession = sqlSessionFactory.openSession();
mapper = sqlSession.getMapper(UserMapper.class);
}
@After
public void close() {
sqlSession.close();
}
@Test
public void testFindAllResultMap() {
List<User> allResultMap = mapper.findAllResultMap();
for (User user : allResultMap) {
System.out.println(user);
}
}
1.2 多条件查询
需求
根据id和username查询user表
方式一
使用 #{arg0}-#{argn}
或者#{param1}-#{paramn}
获取参数
UserMapper 接口
List<User> findByIdAndUsername1(int id, String username);
UserMapper.xml
<select id="findByIdAndUsername1" resultMap="userResultMap">
<!-- select * from `user` where id = #{arg0} and username = #{arg1}-->
select * from `user` where id = #{param1} and username = #{param2}
</select>
测试
@Test
public void test3() throws IOException {
mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.findByIdAndUsername1(3, "zm");
for (User user : users) {
System.out.println(user);
}
}
方式二
使用注解,引入@Param()
注解获取参数
UserMapper 接口
public List<User> findByIdAndUsername2(@Param("id") int id, @Param("username") String username);
UserMapper.xml
<select id="findByIdAndUsername2" resultMap="userResultMap" >
<!-- 注意:此处{}里面的值要和上面的@Param注解里面的value 值保持一致-->
select * from `user` where id = #{id} and username = #{username}
</select>
测试
@Test
public void test4() throws IOException {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.findByIdAndUsername2(4, "zm");
for (User user : users) {
System.out.println(user);
}
}
方式三(推荐)
使用 POJO 对象传递参数
UserMapper 接口
List<User> findByIdAndUsername3(User user);
UserMapper.xml
<select id="findByIdAndUsername3" resultMap="userResultMap" parameterType="com.zm.domain.User">
select * from `user` where id = #{id} and username = #{username}
</select>
测试
@Test
public void test5() throws IOException {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user1 = new User();
user1.setId(1);
user1.setUsername("zm");
List<User> users = mapper.findByIdAndUsername3(user1);
for (User user : users) {
System.out.println(user);
}
}
1.3 模糊查询
方式一
UserMapper 接口
public List<User> findByUsername1(String username);
UserMapper.xml
<select id="findByUsername1" resultMap="userResultMap" parameterType="string">
<!-- #{}在mybatis中是占位符,引用参数值的时候会自动添加单引号 -->
select * from `user` where username like #{username}
</select>
测试
@Test
public void test6() throws IOException {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.findByUsername1("%zm%");
for (User user : users) {
System.out.println(user);
}
}
方式二
UserMapper 接口
List<User> findByUsername2(String username);
UserMapper.xml
<select id="findByUsername2" resultMap="userResultMap" parameterType="string">
<!--parameterType 是基本数据类型或者 String 的时候,
${} 里面的值只能写 value,
${}: sql 原样拼接
-->
select * from `user` where username like '${value}'
</select>
测试
@Test
public void test7() {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.findByUsername2("%zm%");
for (User user : users) {
System.out.println(user);
}
}
${} 与 #{} 区别
#{}表示一个占位符号
- 通过
#{}
可以实现 preparedStatement 向占位符中设置值,自动进行 Java 类型和 JDBC 类型转换,#{}
可以有效防止 SQL 注入。#{}
可以接收简单类型值或 POJO 属性值。- 如果 parameterType 传输单个简单类型值,
#{}
括号中名称随便写。
${} 表示拼接 SQL 串
- 通过
${}
可以将 parameterType 传入的内容拼接在 SQL 中且不进行 JDBC 类型转换,会出现 SQL 注入问题。${}
可以接收简单类型值或 POJO 属性值。- 如果 parameterType 传输单个简单类型值,
${}
括号中只能是 value。
2. MyBatis 映射文件深入
2.1 返回主键
应用场景:向数据库插入一条记录后,希望能立即拿到这条记录在数据库中的主键值。
2.1.1 useGeneratedKeys
注意:只适用于主键自增的数据库,MySQL 和 SQL Server 支持,Oracle 不行。
UserMapper 接口
void saveUser1(User user);
UserMapper.xml
<!--
useGeneratedKeys="true": 声明返回主键
keyProperty="id":把返回主键的值,封装到实体中的那个属性上
-->
<insert id="saveUser1" parameterType="user" useGeneratedKeys="true" keyProperty="id">
insert into `user` (username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address})
</insert>
测试
@Test
public void test8() throws IOException {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setUsername("某冰冰");
user.setBirthday(new Date());
user.setAddress("北京昌平");
user.setSex("女");
System.out.println(user);
mapper.saveUser1(user);
System.out.println(user);
sqlSession.commit();
}
2.1.2 selectKey
UserMapper 接口
public void saveUser2(User user);
UserMapper.xml
<!--
selectKey : 适用范围更广,支持所有类型的数据库
order="AFTER" : 设置在 sql 语句执行后,执行此语句
keyColumn="id" : 指定主键对应列名
keyProperty="id" : 把返回主键的值,封装到实体中的那个属性上
resultType="int" : 指定主键类型
-->
<insert id="saveUser2" parameterType="user" >
<selectKey order="AFTER" keyColumn="id" keyProperty="id" resultType="int"