1. 开发规范
Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。
Mapper接口开发需要遵循以下规范:
- Mapper.xml文件中的namespace与mapper接口的类路径相同,即namespace必须是接口的全限定名。
- Mapper接口方法名和Mapper.xml中定义的每个statement的id相同。
- Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql的parameterType的类型相同。
- Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同。
2. 简单使用Mapper
本项目数据库基于JavaEE Mybatis使用文章
1). 编写Mapper接口
在工程的src目录下新建一个com.mazaiting.mapper包,并在该包下创建一个Mapper接口——UserMapper.java
public interface UserMapper {
User getUserById(int id);
List<User> getUserByName(String username);
void addUser(User user);
}
接口定义有如下特点:
- mapper接口方法名和mapper.xml中定义的statement的id相同。
- mapper接口方法的输入参数类型和mapper.xml中定义的statement的parameterType的类型相同。
- mapper接口方法的输出参数类型和mapper.xml中定义的statement的resultType的类型相同。
2). 编写Mapper.xml(映射文件)
在config源码目录下新建一个mapper的普通文件夹,该文件夹专门用于存放映射文件。然后在该文件夹下创建一个名为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.mazaiting.mapper.UserMapper">
<select id="getUserById" parameterType="int" resultType="com.mazaiting.po.User">
select * from user where id = #{id}
</select>
<select id="getUserByName" parameterType="string" resultType="com.mazaiting.po.User">
select * from user where username like '%${value}%'
</select>
<insert id="addUser" parameterType="com.mazaiting.po.User">
<selectKey keyProperty="id" resultType="int" order="AFTER">
select LAST_INSERT_ID()
</selectKey>
insert into user (username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
</insert>
</mapper>
3). 加载mapper.xml映射文件
在SqlMapConfig.xml文件添加如下配置:
<mapper resource="mapper/mapper.xml"/>
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>
<!-- 和spring整合后environments配置将废除 -->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理 -->
<transactionManager type="JDBC" />
<!-- 数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
<!-- 添加的内容 -->
<mappers>
<!-- resource是基于classpath来查找的 -->
<mapper resource="sqlmap/user.xml"/>
<mapper resource="mapper/mapper.xml"/>
</mappers>
</configuration>
4). 编写测试程序
public class UserMapperTest {
// 单例工厂
private SqlSessionFactory factory;
@Before
public void init() throws IOException {
// 1. 创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 2. 加载配置文件
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
// 3. 创建SqlSessionFactory对象
factory = builder.build(inputStream);
}
@Test
public void testGetUserById() {
// 和Spring整合后就省略了
SqlSession session = factory.openSession();
// 获得代理对象(和Spring整合后只需要通过Spring容器拿到Usermapper接口的搭理对象就可以了)
UserMapper userMapper = session.getMapper(UserMapper.class);
User user = userMapper.getUserById(10);
System.out.println(user);
// 和Spring整合后就省略了
session.close();
}
@Test
public void testGetUserByName() {
SqlSession session = factory.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> list = mapper.getUserByName("张");
for(User user : list) {
System.out.println(user);
}
session.close();
}
@Test
public void testAddUser(){
SqlSession session = factory.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User();
user.setUsername("凌浩雨");
user.setSex("男");
user.setBirthday(new Date());
user.setAddress("理化所");
mapper.addUser(user);
System.out.println(user.getId());
session.commit();
session.close();
}
}
5). 打印结果:
testGetUserById
testGetUserByName
testAddUser
6). 总结
- selectOne和selectList
动态代理对象调用sqlSession.selectOne()和sqlSession.selectList()是根据mapper接口方法的返回值决定,如果返回list则调用selectList方法,如果返回单个对象则调用selectOne方法。 - namespace
mybatis官方推荐使用mapper代理方法开发mapper接口,程序员不用编写mapper接口实现类,使用mapper代理方法时,输入参数可以使用pojo包装对象或map对象,保证dao的通用性。
3. SqlMapConfig.xml配置文件
1). 配置内容
SqlMapConfig.xml文件中配置的内容和顺序如下:
1>. properties(属性)
2>. settings(全局配置参数)
3>. typeAliases(类型别名)
4>. typeHandlers(类型处理器)
5>. objectFactory(对象工厂)
6>. plugins(插件)
7>. environments(环境集合属性对象)
I.environment(环境子属性对象)
1>>.transactionManager(事务管理)
2>>.dataSource(数据源)
8>. mappers(映射器)
2). properties(属性)
在SqlMapConfig.xml配置文件中,我们可把数据库连接信息配置到properties标签当中
<!-- 配置属性 -->
<properties>
<property name="jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="jdbc.url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8"/>
</properties>
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>
<property name="jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="jdbc.url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8"/>
</properties>
<!-- 和spring整合后environments配置将废除 -->
<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="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
<!-- 添加的内容 -->
<mappers>
<!-- resource是基于classpath来查找的 -->
<mapper resource="sqlmap/user.xml"/>
<mapper resource="mapper/mapper.xml"/>
</mappers>
</configuration>
将数据库连接信息配置到一个java属性文件中,然后再来引用其中的配置信息。我按照这种指导思想在classpath下定义一个db.properties文件.
db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root
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">
<!-- <property name="jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="jdbc.url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8"/> -->
<property name="jdbc.driver" value="${jdbc.driver}"/>
<property name="jdbc.url" value="${jdbc.url}"/>
</properties>
<!-- 和spring整合后environments配置将废除 -->
<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>
<!-- resource是基于classpath来查找的 -->
<mapper resource="sqlmap/user.xml"/>
<mapper resource="mapper/mapper.xml"/>
</mappers>
</configuration>
3). typeAliases(类型别名)
- mybatis支持别名
别名 | 映射的类型 |
---|---|
_byte | byte |
_long | long |
_short | short |
_int | int |
_integer | int |
_double | double |
_float | float |
_boolean | boolean |
string | String |
byte | Byte |
long | Long |
short | Short |
int | Integer |
integer | Integer |
double | Double |
float | Float |
boolean | Boolean |
date | Date |
decimal | BigDecimal |
bigdecimal | BigDecimal |
map | Map |
- 自定义别名
在SqlMapConfig.xml文件中添加:
<!-- 配置pojo的别名 -->
<typeAliases>
<!-- 单个定义别名,别名不区分大小写 -->
<typeAlias type="com.mazaiting.po.User" alias="User"/>
</typeAliases>
则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.mazaiting.mapper.UserMapper">
<!-- 应用别名 -->
<select id="getUserById" parameterType="int" resultType="User">
select * from user where id = #{id}
</select>
<select id="getUserByName" parameterType="string" resultType="com.mazaiting.po.User">
select * from user where username like '%${value}%'
</select>
<insert id="addUser" parameterType="com.mazaiting.po.User">
<selectKey keyProperty="id" resultType="int" order="AFTER">
select LAST_INSERT_ID()
</selectKey>
insert into user (username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
</insert>
</mapper>
注意:resultType属性的值就是User类的别名,且别名是不区分大小写的.
- 批量定义别名
<!-- 配置pojo的别名 -->
<typeAliases>
<!-- 批量别名定义,扫描包的形式创建别名,别名就是类名,且不区分大小写 -->
<package name="com.mazaiting.po"/>
</typeAliases>
4). SqlMapConfig.xml文件加载mapper.xml文件
- <mapper resource=" " />
使用相对于类路径的资源,如
<mapper resource="sqlmap/user.xml"/>
- <mapper class=" " />
使用mapper接口类路径,如:
<mapper class="com.mazaiting.mapper.UserMapper"/>
注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。
- <package name=""/>
注册指定包下的所有mapper接口,如:
<package name="com.mazaiting.mapper"/>
注意:此种方法要求mapper接口名称和mapper映射文件名称相同,且放在同一个目录中。
4. 输入映射--parameterType(输入类型)
1). 传递简单类型
<select id="getUserById" parameterType="int" resultType="com.mazaiting.po.User">
select * from user where id = #{id};
</select>
2). 传递pojo对象
MyBatis使用ognl表达式解析对象字段的值,#{}或者${}括号中的值为pojo属性名称。
<insert id="addUser" parameterType="com.mazaiting.po.User">
insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
</insert>
3). 传递pojo包装对象
I. 在com.mazaiting.po包下新建QueryVo类
public class QueryVo {
private User user;
public void setUser(User user) {
this.user = user;
}
public User getUser() {
return user;
}
}
II. 在UserMapper.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.mazaiting.mapper.UserMapper">
<select id="getUserByQueryVo" parameterType="queryvo" resultType="user">
select * from user where id = #{user.id}
</select>
</mapper>
III. 在UserMapper接口中添加方法
public interface UserMapper {
User getUserByQueryVo(QueryVo queryVo);
}
IV. 编写测试代码
public class UserMapperTest {
// 单例工厂
private SqlSessionFactory factory;
@Before
public void init() throws IOException {
// 1. 创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 2. 加载配置文件
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
// 3. 创建SqlSessionFactory对象
factory = builder.build(inputStream);
}
@Test
public void testGetUserByQueryVo(){
SqlSession session = factory.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
QueryVo queryVo = new QueryVo();
User user = new User();
user.setId(10);
queryVo.setUser(user);
User queryUser = mapper.getUserByQueryVo(queryVo);
System.out.println(queryUser);
session.close();
}
}
V. 打印结果:
4). 传递HashMap(传递HashMap在实际开发中用的很少)
I. 在UserMapper中添加查询方法
<?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.mazaiting.mapper.UserMapper">
<!-- 传递HashMap综合查询用户信息 -->
<select id="findUserByHashMap" parameterType="hashmap" resultType="user">
select * from user where id = #{id} and username like '%${username}%'
</select>
</mapper>
注:id和username是HashMap的key。
II. 在UserMapper中添加接口方法
public interface UserMapper {
User findUserByHashMap(HashMap<String, Object> map);
}
III. 编写测试方法
public class UserMapperTest {
// 单例工厂
private SqlSessionFactory factory;
@Before
public void init() throws IOException {
// 1. 创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 2. 加载配置文件
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
// 3. 创建SqlSessionFactory对象
factory = builder.build(inputStream);
}
@Test
public void testFindUserByHashMap(){
SqlSession session = factory.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
HashMap<String, Object> map = new HashMap<>();
map.put("id", 10);
map.put("username", "张");
User user = mapper.findUserByHashMap(map);
System.out.println(user);
session.close();
}
}
IV. 打印结果
5. 输出映射--resultType(输出类型)
1). 输出简单类型
I. 在UserMapper.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.mazaiting.mapper.UserMapper">
<!-- 查询表中的记录数 -->
<select id="getUserCount" resultType="int">
select COUNT(*) from user
</select>
</mapper>
II. 在UserMapper接口中添加方法
public interface UserMapper {
Integer getUserCount();
}
III. 编写测试方法
public class UserMapperTest {
// 单例工厂
private SqlSessionFactory factory;
@Before
public void init() throws IOException {
// 1. 创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 2. 加载配置文件
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
// 3. 创建SqlSessionFactory对象
factory = builder.build(inputStream);
}
@Test
public void testGetUserCount(){
SqlSession session = factory.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
int count = mapper.getUserCount();
System.out.println("共有 " + count + "条记录");
session.close();
}
}
IV. 打印结果:
2). 输出pojo对象
<insert id="addUser" parameterType="com.mazaiting.po.User">
<selectKey keyProperty="id" resultType="int" order="AFTER">
select LAST_INSERT_ID()
</selectKey>
insert into user (username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
</insert>
3). 输出pojo列表
<select id="getUserByName" parameterType="string" resultType="com.mazaiting.po.User">
select * from user where username like '%${value}%'
</select>
4). 当pojo中属性名和数据库中字段名不相同时
I. 在com.mazaiting.po包下创建Order.java
public class Order {
private Integer id;
private Integer userId;
private String number;
private Date createtime;
private String note;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public Date getCreatetime() {
return createtime;
}
public void setCreatetime(Date createtime) {
this.createtime = createtime;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
@Override
public String toString() {
return "Order [id=" + id + ", userId=" + userId + ", number=" + number + ", createtime=" + createtime
+ ", note=" + note + "]";
}
}
II. 在com.mazaiting.mapper包下创建接口OrderMapper
public interface OrderMapper {
}
III. 在com.mazaiting.mapper包下创建OrderMapper.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.mazaiting.mapper.OrderMapper">
<select id="getOrderList" resultType="order">
select * from order
</select>
</mapper>
IV. 在OrderMapper接口中添加方法
public interface OrderMapper {
List<Order> getOrderList();
}
V. 编写测试方法
public class OrderMapperTest {
SqlSessionFactory factory;
@Before
public void init() throws IOException {
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
factory = builder.build(inputStream);
}
@Test
public void testGetOrderList() {
SqlSession session = factory.openSession();
OrderMapper mapper = session.getMapper(OrderMapper.class);
List<Order> list = mapper.getOrderList();
for (Order order : list) {
System.out.println(order);
}
session.close();
}
}
VI. 打印结果
可以看到userId读取出来为null,原因 数据库表中的字段名为user_id.
5). 获取userId解决办法1
将OrderMapper.xml文件中的
<select id="getOrderList" resultType="order">
select * from order
</select>
修改为
<select id="getOrderList" resultType="order">
select id,user_id userId,number,createtime,note from orders
</select>
执行测试方法,打印结果:
6). 获取userId解决办法2-- resultMap
resultMap可以指定pojo将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,resultMap实质上还需要将查询结果映射到pojo对象中。
resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。
- type:指resultMap要映射成的数据类型(返回结果映射的pojo,可以使用别名)。
- <id />:此属性表示查询结果集的唯一标识,非常重要。如果是多个字段为复合唯一约束则定义多个<id />。
- property:表示Orders类的属性。
- column:表示sql查询出来的字段名。
column和property放在一块儿表示将sql查询出来的字段映射到指定的pojo类属性上。 - <result />:普通列使用result标签映射。
解决办法:
将OrderMapper.xml文件中的
<select id="getOrderList" resultType="order">
select * from order
</select>
修改为
<resultMap type="order" id="order_list_result_map">
<!-- id是主键的映射,其中property是pojo中主键的属性,column是返回主键的列 -->
<id property="id" column="id"/>
<!-- 普通列使用result映射 -->
<result property="userId" column="user_id"/>
<result property="number" column="number"/>
<result property="createtime" column="createtime"/>
<result property="note" column="note"/>
</resultMap>
<!-- 使用resultMap方式 -->
<select id="getOrderList" resultMap="order_list_result_map">
select * from orders
</select>
执行测试并打印:
6. 动态SQL
1). if标签
I. 在UserMapper.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.mazaiting.mapper.UserMapper">
<select id="findUserList" parameterType="user" resultType="user">
select * from user
where 1=1
<if test="id!=null">
and id = #{id}
</if>
<if test="username!=null and username !=''">
and username like '%${username}%'
</if>
</select>
</mapper>
注意:
- username要做不等于空字符串的校验。
- User类中id属性的类型要改为Integer包装类型,因为int类型的id是不可能为null的!
II. 在UserMapper中添加方法
public interface UserMapper {
List<User> findUserList(User user);
}
III. 测试方法
public class UserMapperTest {
// 单例工厂
private SqlSessionFactory factory;
@Before
public void init() throws IOException {
// 1. 创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 2. 加载配置文件
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
// 3. 创建SqlSessionFactory对象
factory = builder.build(inputStream);
}
@Test
public void testFindUserList(){
SqlSession session = factory.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User();
user.setId(10);
List<User> list = mapper.findUserList(user);
for (User nUser : list) {
System.out.println(nUser);
}
session.close();
}
}
IV. 执行测试方法,打印结果:
2). where标签
可将上个例子中的UserMapper.xml文件中
<select id="findUserList" parameterType="user" resultType="user">
select * from user
where 1=1
<if test="id!=null">
and id = #{id}
</if>
<if test="username!=null and username !=''">
and username like '%${username}%'
</if>
</select>
修改为:
<select id="findUserList" parameterType="user" resultType="user">
select * from user
<where>
<if test="id!=null">
and id = #{id}
</if>
<if test="username!=null and username !=''">
and username like '%${username}%'
</if>
</where>
</select>
执行测试代码,打印结果:
3). foreach
I. 在QueryVo类中添加id列表属性
public class QueryVo {
private User user;
private List<Integer> ids;
public void setUser(User user) {
this.user = user;
}
public User getUser() {
return user;
}
public void setIds(List<Integer> ids) {
this.ids = ids;
}
public List<Integer> getIds() {
return ids;
}
}
II. 在UserMapper.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.mazaiting.mapper.UserMapper">
<!-- 动态sql foreach测试 -->
<select id="findUserByIds" parameterType="queryvo" resultType="user">
select * from user
<where>
<!-- and id in(1,10,20,21,31)
collection 遍历的集合
item 条目
open 循环之前的内容
close 循环之后的内容
separator 分隔符
-->
<foreach collection="ids" item="id" open="and id in(" close=")" separator=",">
#{id}
</foreach>
</where>
</select>
</mapper>
III. 在UserMapper接口中添加方法
public interface UserMapper {
List<User> findUserByIds(QueryVo queryVo);
}
IV. 测试方法
public class UserMapperTest {
// 单例工厂
private SqlSessionFactory factory;
@Before
public void init() throws IOException {
// 1. 创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 2. 加载配置文件
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
// 3. 创建SqlSessionFactory对象
factory = builder.build(inputStream);
}
@Test
public void testFindUserByIds(){
SqlSession session = factory.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
QueryVo queryVo = new QueryVo();
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(10);
list.add(16);
list.add(22);
queryVo.setIds(list);
List<User> userList = mapper.findUserByIds(queryVo);
for (User user : userList) {
System.out.println(user);
}
session.close();
}
}
V. 测试方法打印结果:
4). sql片段
sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的
将下面的select方法使用sql片段:
<select id="findUserList" parameterType="user" resultType="user">
select * from user
<where>
<if test="id!=null">
and id = #{id}
</if>
<if test="username!=null and username !=''">
and username like '%${username}%'
</if>
</where>
</select>
修改为:
<!-- 查询字段 -->
<sql id="user_field_list">
id,username,birthday,sex,address
</sql>
<!-- 抽取where条件 -->
<sql id="find_user_list_where">
<where>
<if test="id!=null">
and id = #{id}
</if>
<if test="username!=null and username !=''">
and username like '%${username}%'
</if>
</where>
</sql>
<select id="findUserList" parameterType="user" resultType="user">
select <include refid="user_field_list"/> from user
<include refid="find_user_list_where"/>
</select>
5).注意:如果引用其它mapper.xml映射文件的sql片段,则在引用时需要加上namespace,如下:
<include refid="namespace.sql片段id"/>
7. 一对一关联映射
1). 一对一查询--方法一
I. 创建OrderUser类,并继承Order类
public class OrderUser extends Order{
private String username;
private String address;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "OrderUser [username=" + username + ", address=" + address + ", getId()=" + getId() + ", getUserId()="
+ getUserId() + ", getNumber()=" + getNumber() + ", getCreatetime()=" + getCreatetime() + ", getNote()="
+ getNote();
}
}
II. 在OrderMapper.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.mazaiting.mapper.OrderMapper">
<select id="getOrderUserList" resultType="orderuser">
select
o.id,
o.user_id userId,
o.number,
o.createtime,
o.note,
u.username,
u.address
from
orders o
left join user u on o.user_id = u.id
</select>
</mapper>
III. 在OrderMapper中添加方法
public interface OrderMapper {
List<OrderUser> getOrderUserList();
}
IV. 测试方法
public class OrderMapperTest {
SqlSessionFactory factory;
@Before
public void init() throws IOException {
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
factory = builder.build(inputStream);
}
@Test
public void testGetOrderUserList(){
SqlSession session = factory.openSession();
OrderMapper mapper = session.getMapper(OrderMapper.class);
List<OrderUser> list = mapper.getOrderUserList();
for (OrderUser orderUser : list) {
System.out.println(orderUser.toString());
}
session.close();
}
}
V. 打印结果:
注意:定义专门的po类作为输出类型,其中定义了sql查询结果集所有的字段。此方法较为简单,企业中使用普遍。
2). 一对一查询--方法二
使用resultMap,定义专门的resultMap用于映射一对一查询结果。首先在Order类中加入user属性,user属性中用于存储关联查询的用户信息,因为订单关联查询用户是一对一关系,所以这里使用单个User对象存储关联查询的用户信息。
I. 修改Order类:
public class Order {
private Integer id;
private Integer userId;
private String number;
private Date createtime;
private String note;
private User user;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public Date getCreatetime() {
return createtime;
}
public void setCreatetime(Date createtime) {
this.createtime = createtime;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String toString() {
return "Order [id=" + id + ", userId=" + userId + ", number=" + number + ", createtime=" + createtime
+ ", note=" + note + ", user=" + user + "]";
}
}
II. 在OrderMapper.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.mazaiting.mapper.OrderMapper">
<resultMap type="order" id="order_user_resultmap">
<id property="id" column="id"/>
<result property="userId" column="user_id"/>
<result property="number" column="number"/>
<result property="createtime" column="createtime"/>
<result property="note" column="note"/>
<!-- 配置一对一关联映射 -->
<association property="user" javaType="com.mazaiting.po.User">
<id property="id" column="user_id"/>
<result property="username" column="username"/>
<result property="address" column="address"/>
</association>
</resultMap>
<select id="getOrderUserResultMap" resultMap="order_user_resultmap">
select
o.id,
o.user_id,
o.number,
o.createtime,
o.note,
u.username,
u.address
from
orders o
left join user u on o.user_id = u.id
</select>
</mapper>
- association:表示进行关联查询单条记录。
- property:表示关联查询的结果存储在com.mazaiting.po.Order的user属性中。即property对应Orders类里面一对一关联映射的那个属性,即user属性。
- javaType:表示关联查询的结果类型。即user属性的数据类型,可使用别名。
-
<id property="id" column="user_id"/>
:查询结果的user_id列对应关联对象的id属性,这里是<id />表示user_id是关联查询对象的唯一标识。 -
<result property="username" column="username"/>
:查询结果的username列对应关联对象的username属性。
III. 在OrderMapper接口中完成方法
public interface OrderMapper {
List<Order> getOrderUserResultMap();
}
IV. 测试方法
public class OrderMapperTest {
SqlSessionFactory factory;
@Before
public void init() throws IOException {
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
factory = builder.build(inputStream);
}
@Test
public void testGetOrderUserResultMap(){
SqlSession session = factory.openSession();
OrderMapper mapper = session.getMapper(OrderMapper.class);
List<Order> list = mapper.getOrderUserResultMap();
for (Order order : list) {
System.out.println(order.toString());
}
session.close();
}
}
V. 打印结果:
总结:使用association完成关联查询,将关联查询信息映射到pojo对象中。
3). 一对多关联映射
I. 在User类中加入List<Orders> orders属性
public class User {
// id
private int id;
// 用户名
private String username;
// 性别
private String sex;
// 用户名
private Date birthday;
// 地址
private String address;
private List<Order> orders;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public List<Order> getOrders() {
return orders;
}
public void setOrders(List<Order> orders) {
this.orders = orders;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", sex=" + sex + ", birthday=" + birthday + ", address="
+ address + ", orders=" + orders + "]";
}
}
II. 在UserMapper.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.mazaiting.mapper.UserMapper">
<resultMap type="user" id="user_order_resultmap">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="birthday" column="birthday"/>
<result property="sex" column="sex"/>
<result property="address" column="address"/>
<!-- 配置一对多映射 -->
<collection property="orders" ofType="order">
<id property="id" column="oid"/>
<result property="number" column="number"/>
<result property="createtime" column="createtime"/>
<result property="note" column="note"/>
</collection>
</resultMap>
<select id="getUserWithOrders" resultMap="user_order_resultmap">
select
u.id,
u.username,
u.birthday,
u.sex,
u.address,
o.id oid,
o.number,
o.createtime,
o.note
from
user u
left join orders o on u.id = o.user_id
</select>
</mapper>
- collection部分定义了用户关联的订单信息。表示关联查询结果集。
- property=”orders”:关联查询的结果集存储在User对象的哪个属性上。即property对应User对象中的集合属性。
- ofType=”order”:指定关联查询的结果集中的对象类型即List中的对象类型。此处可以使用别名,也可以使用全限定名。
- <id />及<result/>的意义同一对一查询。
III. 在UserMapper接口中添加方法
public interface UserMapper {
List<User> getUserWithOrders();
}
IV. 测试方法
public class UserMapperTest {
// 单例工厂
private SqlSessionFactory factory;
@Before
public void init() throws IOException {
// 1. 创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
// 2. 加载配置文件
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
// 3. 创建SqlSessionFactory对象
factory = builder.build(inputStream);
}
@Test
public void testGetUserWithOrders(){
SqlSession session = factory.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> list =mapper.getUserWithOrders();
for (User user : list) {
System.out.println(user.toString());
}
session.close();
}
}
V. 执行测试,打印结果: