Mapper.xml映射文件定义了操作数据的sql,这里的每个sql都是一个statement。
输入映射 parameterType
- 简单类型: int string double
- pojo
- 包装类型的pojo
- map
- list
- 多参数传递
输出映射
resultType
- 简单类型
- pojo
- List
- map
总结
1)输出pojo和输出List在statement中定义的resultType类型是一致的
2)使用resultType进行输出映射,只有查询出来的列名和POJO中的属性名一致才能映射成功
如果查询出的字段和pojo中的属性至少一个匹配就能创建pojo对象,没有一个匹配的则不会创建pojo对象
resultMap(高级映射)
基本概念
1)如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段和属性名建立对应关系
2)resultMap可以实现将查询结果集映射为复杂类型的pojo,就是高级映射
使用resultMap进行输出映射步骤
- 定义一个resultMap:将查询的字段名和pojo中的属性做一个映射关系
- 指定statement中的resultMap:引用resultMap
内容
- 一对一查询
- 一对多查询
- 多对多查询
动态SQL
概念
含义:动态SQL就是对SQL语句进行灵活操作,通过表达式进行判断,对sql进行灵活判断
需求:用户信息的综合查询(用户信息,订单信息,商品信息)
解决方案:通过动态SQL的各种标签对查询条件进行判断,如果输入参数(查询条件)不为空,才进行sql操作
实例
SqlMapConfig.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>
<!-- 加载外部属性文件 -->
<properties resource="db.properties"></properties>
<!-- 别名定义 -->
<typeAliases>
<!--
1.针对单个别名定义
type:类型的路径
alias:别名
-->
<!-- <typeAlias type="com.hpe.mybatis.po.User" alias="user"/> -->
<!--
2.批量定义别名:mybatis可以自动扫描包中的po类,自动定义别名
name:指定包名
别名:类名(首字母不区分大小)
-->
<package name="com.hpe.mybatis.po"/>
<!-- 可以指定多个package -->
</typeAliases>
<!-- 类型处理器的配置 -->
<!-- 配置Mybatis运行环境 -->
<!-- 将来和spring整合之后,配置运行环境就废弃了 -->
<environments default="development">
<environment id="development">
<!-- 事务管理器:使用JDBC事务管理 -->
<transactionManager type="JDBC" />
<!-- 配置数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
</environment>
</environments>
<!-- 加载映射文件 -->
<mappers>
<!-- <mapper resource="mybatis/UserMapper.xml"/> -->
<!-- 1.resource:只能加载一个映射文件,指的是相对于类路径的资源 -->
<!-- <mapper resource="UserMapper.xml"/> -->
<!-- <mapper url=""/> -->
<!-- 2.class:使用mapper接口类路径的方式
要求:此种方式要求mapper接口的名称和mapper映射文件名称相同且在同一个目录
-->
<!-- <mapper class="com.hpe.mybatis.mapper.UserMapper"/> -->
<!-- 3.批量加载 name:指定mapper接口的包名,mybatis会自动扫描包下的所有接口进行加载
要求:此种方式要求mapper接口的名称和mapper映射文件名称相同且在同一个目录
规范:使用mapper接口类路径的方式和批量加载的方式前提是使用mapper动态代理的开发方式
-->
<package name="com.hpe.mybatis.mapper"/>
</mappers>
</configuration>
mapper.java接口文件
package com.hpe.mybatis.mapper;
import java.util.List;
import com.hpe.mybatis.po.User;
import com.hpe.mybatis.po.UserQueryVo;
public interface UserMapper {
// 完成用户的综合查询(姓名和性别)
List<User> findUserByQuery(UserQueryVo userQueryVo);
// 获取用户记录总数
int findUserCount();
// 根据id查询用户信息
User findUserById(int id);
// 根据用户名模糊查询用户信息
List<User> findUserByName(String name);
// 根据用户id查询用户信息(根据输出映射)
User findUserByIdResultMap(int id);
// 用户信息综合查询2(使用用户名、性别作为查询条件)
List<User> findUserByUser(User user);
// 根据用户id更新用户信息
int updateUser(User user);
}
mapper.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.hpe.mybatis.mapper.UserMapper">
<!-- 定义resultMap:对查询的column和property建立对应关系
type:输出映射所对应的Java对象类型,可以使用别名
id:对这个resultMap的唯一标识
-->
<resultMap type="User" id="userResultMap">
<!-- id:查询结果集中的唯一标识(表中的主键)
property:type指定的pojo类型中的属性名
column:查询出来的列名
-->
<id column="userId" property="id"/>
<!-- 对普通列进行映射 -->
<result column="name" property="username"/>
<result column="sex_" property="sex"/>
<result column="address_" property="address"/>
</resultMap>
<!-- 定义SQL片段:可以实现共享,作为综合查询条件的一部分
注意:基于单表定义的SQL判断,SQL片段的重用性比较高
id:sql片段的唯一标识
在SQL中不要加上where,一个SQL可能增加多个SQL片段
-->
<sql id="query_user">
<if test="username!=null and username!=''">
AND username LIKE '%${username}%'
</if>
<if test="sex!=null and sex!=''">
AND sex = #{sex}
</if>
</sql>
<!-- 根据姓名和性别查询 -->
<select id="findUserByQuery" parameterType="UserQueryVo" resultType="User">
SELECT * FROM user WHERE username LIKE '%${user.username}%' AND sex = #{user.sex}
</select>
<!-- 获取用户记录总数 -->
<select id="findUserCount" resultType="int">
SELECT COUNT(*) FROM user
</select>
<!-- 根据id查询用户信息 -->
<select id="findUserById" parameterType="int" resultType="User">
SELECT * FROM user WHERE id = #{id}
</select>
<!-- 根据用户名模糊查询用户信息 -->
<select id="findUserByName" parameterType="string" resultType="User">
SELECT * FROM user WHERE username LIKE '%${value}%'
</select>
<!-- 使用resultMap进行输出映射
resultMap:引用resultMap的id,如果引用的resultMap在其他map文件中,需要加上namespace
-->
<select id="findUserByIdResultMap" parameterType="int" resultMap="userResultMap">
SELECT id userId,username name,sex sex_,address address_ FROM user WHERE id = #{id}
</select>
<!-- 使用动态SQL实现用户查询
根据user的username和sex属性是否为空,动态生成SQL
-->
<select id="findUserByUser" parameterType="User" resultType="User">
SELECT * FROM user
<!-- where:可以自动去掉条件中的第一个and -->
<where>
<!-- 引入SQL片段
refid:指定SQL片段的标识(id)
如果引入的SQL片段不在次mapper.xml文件中,需要加上namespace
可以引入多个SQL片段
-->
<include refid="query_user"></include>
</where>
</select>
<!-- 根据用户id更新用户信息 -->
<update id="updateUser" parameterType="User">
<!-- UPDATE user SET username = #{username},sex = #{sex},address = #{address} WHERE id = #{id} -->
UPDATE user
<!-- set:会动态前置set关键字,同时会消除sql语句中多余的逗号 -->
<set>
<if test="username!=null and username!=''">
username = #{username},
</if>
<if test="sex!=null and sex!=''">
sex = #{sex},
</if>
<if test="address!=null and address!=''">
address = #{address},
</if>
</set>
WHERE id = #{id}
</update>
</mapper>
测试test
package com.hpe.mybatis.test;
import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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.Before;
import org.junit.Test;
import com.hpe.mybatis.mapper.UserMapper;
import com.hpe.mybatis.po.User;
import com.hpe.mybatis.po.UserQueryVo;
public class UserMapperTest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void setUp() throws Exception {
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// 创建会话工厂,传入Mybatis配置信息
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
// 用户信息的综合查询
@Test
public void testFindUserByQuery(){
// 根据会话工厂创建会话
SqlSession sqlSession = sqlSessionFactory.openSession();
// 使用mybatis动态代理的方式生成代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
UserQueryVo userQueryVo = new UserQueryVo();
User user = new User();
user.setUsername("小");
user.setSex("2");
userQueryVo.setUser(user);
List<User> list = userMapper.findUserByQuery(userQueryVo);
sqlSession.close();
System.out.println(list);
}
// 查询用户记录总数
@Test
public void testFindUserCount(){
// 根据会话工厂创建会话
SqlSession sqlSession = sqlSessionFactory.openSession();
// 使用mybatis动态代理的方式生成代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
int count = userMapper.findUserCount();
sqlSession.close();
System.out.println(count);
}
// 根据id查询用户信息
@Test
public void testFindUserById(){
// 根据会话工厂创建会话
SqlSession sqlSession = sqlSessionFactory.openSession();
// 使用mybatis动态代理的方式生成代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.findUserById(1);
sqlSession.close();
System.out.println(user);
}
// 根据用户名模糊查询用户信息
@Test
public void testFindUserByName(){
// 根据会话工厂创建会话
SqlSession sqlSession = sqlSessionFactory.openSession();
// 使用mybatis动态代理的方式生成代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> list = userMapper.findUserByName("小");
sqlSession.close();
System.out.println(list);
}
// 根据用户名id查询用户信息(输出ResultMap)
@Test
public void testFindUserByIdResultMap(){
// 根据会话工厂创建会话
SqlSession sqlSession = sqlSessionFactory.openSession();
// 使用mybatis动态代理的方式生成代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.findUserByIdResultMap(1);
sqlSession.close();
System.out.println(user);
}
// 根据动态SQL查询用户信息
@Test
public void testFindUserByUser(){
// 根据会话工厂创建会话
SqlSession sqlSession = sqlSessionFactory.openSession();
// 使用mybatis动态代理的方式生成代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setSex("2");
user.setUsername("小");
List<User> list = userMapper.findUserByUser(user);
sqlSession.close();
System.out.println(list);
}
// 根据动态SQL根据用户id更新用户信息
@Test
public void testUpdateUser(){
// 根据会话工厂创建会话
SqlSession sqlSession = sqlSessionFactory.openSession();
// 使用mybatis动态代理的方式生成代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setId(26);
user.setSex("2");
//user.setUsername("小");
int count = userMapper.updateUser(user);
sqlSession.commit();
sqlSession.close();
System.out.println(count);
}
}
动态SQL的foreach标签
UserMapper.java
// 查询多个用户的信息
List<User> selectUserById(List<Integer> ids);
UserMapper.xml
<!-- 查询多个用户信息:可以使用两种方式实现
1.SELECT * FROM user WHERE id = 24 OR id = 25
2.SELECT * FROM user WHERE id IN (24,25)
-->
<select id="selectUserById" parameterType="list" resultType="User">
SELECT * FROM user WHERE
<!-- 第一种方式
1.collection:指定输出对象中的集合属性,其值list:是默认情况使用
其值也可以用注解的方式在接口方法参数处声明集合名称
2.item:集合遍历的每个对象(集合中迭代的别名)
3.open:foreach代码的开始符号
4.close:foreach代码的结束符号
5.separator:元素之间的分隔符
-->
<!-- <foreach collection="list" item="id" open="(" close=")" separator="OR">
每次遍历要拼接的串
id = #{id}
</foreach> -->
<foreach collection="list" item="id" open="id IN (" close=")" separator=",">
<!-- 每次遍历要拼接的串 -->
#{id}
</foreach>
</select>
UserMapperTest.java
// 查询多个用户信息
@Test
public void testSelectUserByIds(){
// 根据会话工厂创建会话
SqlSession sqlSession = sqlSessionFactory.openSession();
// 使用mybatis动态代理的方式生成代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<Integer> ids = new ArrayList<>();
ids.add(24);
ids.add(25);
ids.add(26);
List<User> list = userMapper.selectUserById(ids);
sqlSession.close();
System.out.println(list);
}