mybatis-动态代理式模式详细
核心配置文件:SqlMapConfig.xml
该配置文件主要注意:
- 加载参数配置
- typeAliases 别名的配置 (包扫描方式)
- mappers 加载映射文件配置(映射文件包扫描,推荐方式:)
<?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="jdbc.properties">
<property name="jdbc.username" value="root1"/>
<property name="jdbc.password" value="root"/>
</properties>
<typeAliases>
<!-- 单个别名定义,别名的使用,不区分大小写 -->
<!-- <typeAlias type="com.User" alias="user"/> -->
<!-- 别名包扫描器:别名是类的全称,不区分大小写,推荐方式 -->
<package name="com.bo"/>
</typeAliases>
<!-- 和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>
<!-- 映射文件包扫描,推荐方式:
1、接口文件必须与映射文件同一目录下
2、接口文件名称必须与映射文件的名称一致 -->
<package name="com.mapper"/>
</mappers>
</configuration>
映射文件
下边以UserMapper.xml 示例
需要注意的点:
- 动态代理开发规则:
- namespace必需是接口的全路径名
- 接口的方法名必需与sql id 一致
- 接口的入参与parameterType类型一致
- 接口的返回值必须与resultType类型一致
- 多参数查询时 where 和 if 标签 的使用
- foreach循环标签collection:要遍历的集合
1. open: 循环开始之前输出的内容
2. item: 设置的循环变量
3. separator : 分隔符
4. close : 循环结束周输出的内容 - 使用result绑定普通字段 , 以及sql语句起别名
- collection用于配置一对多关联
property:User当中Order的属性
ofType:orders的数据类型,支持别名
<?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">
<!-- namespace:命名空间,用于隔离sql语句 #{}:占位符,相当于jdbc的? ${}:字符串拼接指令,如果入参为普通数据类型{}内部只写value -->
<!-- 动态代理开发规则: 1、namespace必需是接口的全路径名 2、接口的方法名必需与sql id 一致 3、接口的入参与parameterType类型一致
4、接口的返回值必须与resultType类型一致 -->
<!-- 如果在SqlMapConfig.xml里边使用包扫描的方式或类加载模式加载映射文件的话, -->
<mapper namespace="com.mapper.UserMapper">
<!-- sql片段的抽取,定义 -->
<sql id="user_sql">
`id`,
`username`,
`birthday`,
`sex`,
`address`
</sql>
<!-- id:sql id,语句的唯一标识 parameterType:入参的数据类型 resultType:返回结果的数据类型 -->
<select id="getUserById" parameterType="int" resultType="uSEr">
SELECT
<!-- sql片段使用:refid引用定义好的sql片段id -->
<include refid="user_sql" />
FROM `user`
WHERE id = #{id2}
</select>
<!-- resultType:如果返回结果为集合,只需设置为每一个的数据类型 -->
<select id="getUserByUserName" parameterType="string"
resultType="com.bo.User">
SELECT
<include refid="user_sql" />
FROM `user`
<!-- WHERE username LIKE #{name} -->
WHERE username LIKE '%${value}%'
</select>
<!-- 插入用户 -->
<!-- useGeneratedKeys:使用自增 keyProperty与之配套使用,这里是user的主键 -->
<insert id="insertUser" parameterType="com.bo.User"
useGeneratedKeys="true" keyProperty="id">
<!-- selectKey:主键返回 keyProperty:user中的主键属性 resultType:主键数据类型 order:指定selectKey何时执行:AFTER之后 -->
<!-- <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>
<!-- 删除用户 -->
<delete id="deleteUser" parameterType="Integer" >
DELETE FROM `user` WHERE `id` = #{id}
</delete>
<!-- =============================================== 进阶 ======================================== -->
<!-- 包装类 -->
<!-- Mybatis使用ognl表达式解析对象字段的值,#{}或者${}括号中的值为pojo属性名称。 -->
<!-- resultType:如果返回结果为集合,只需设置为每一个的数据类型 -->
<select id="getUserByQueryVo" parameterType="queryvo" resultType="user">
SELECT
<!-- sql片段使用:refid引用定义好的sql片段id -->
<include refid="user_sql" />
From `user`
<!-- 注意 这里不要忘记加上user. 否则匹配不上-->
Where id = #{user.id}
</select>
<!-- 多参数查询 : <where> <if> 的使用 -->
<select id="getUsersByQueryVo" parameterType ="user" resultType="user">
SELECT
<!-- sql片段使用:refid引用定义好的sql片段id -->
<include refid="user_sql" />
From `user`
<!-- WHERE username LIKE #{name} -->
<!-- 使用where、if 标签 -->
<!-- <where> 自动补上where关键字,同时处理多余的and,用了where标签就不能再手动加上where关键字 -->
<where>
<!-- 经过测试 test之内不能用ognl表达式, 否则 if 语句会失效 -->
<if test="username != null and username != '' ">
and username LIKE '%${username}%'
</if>
<if test="sex != null and sex != '' ">
and sex = #{sex}
</if>
</where>
</select>
<!-- sql语句 in 的实现 : foreach循环标签 -->
<select id="getUserByIds" parameterType="queryvo" resultType="user">
SELECT
<include refid="user_sql"/>
FROM `user`
<where>
<!-- foreach循环标签collection:要遍历的集合
open: 循环开始之前输出的内容 item: 设置的循环变量
separator : 分隔符
close : 循环结束周输出的内容
-->
<!-- 目的:id IN(1,25,29,30,35) -->
<foreach collection="ids" open="id IN(" item="uId" separator="," close=")">
#{uId}
</foreach>
</where>
</select>
<!-- 使用result绑定普通字段 -->
<resultMap type="user" id="user_order_map">
<!-- <id>用于映射主键 -->
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="address" column="address"/>
<result property="birthday" column="birthday"/>
<result property="sex" column = "sex"/>
<!-- collection用于配置一对多关联
property:User当中Order的属性
ofType:orders的数据类型,支持别名
-->
<collection property="orders" ofType="order">
<!-- <id>用于映射主键 -->
<!-- 这里column写的oid是根据sql语句中的别名写的。为何写别名? 可能和user的id冲突 -->
<!-- 需要注意property 是指对象属性的, column是指sql查询语句的字段的,如果有别名的话需要写别名。 -->
<id property="id" column="oid"/>
<result property="userId" column="id"/><!-- 注意:这里的id 是 user表里的id property对应的是order表里的。该配置=`user_id` = u.`id` -->
<result property="number" column="number"/>
<result property="createtime" column="createtime"/>
<result property="note" column="note"/>
</collection>
</resultMap>
<select id="getUserOrderMap" resultMap="user_order_map">
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 `order` o
ON o.`user_id` = u.`id`
</select>
</mapper>
实体类示例
接口示例
package com.mapper;
import java.util.List;
import com.bo.QueryVo;
import com.bo.User;
/**
* 用户信息持久化接口 动态代理 不需要实现类
* @author Steven
*
*/
public interface UserMapper {
/**
* 根据用户ID查询用户信息
* @param id
* @return
*/
User getUserById(Integer id);
/**
* 根据用户名查找用户列表
* @param userName
* @return
*/
List<User> getUserByUserName(String userName);
/**
* 添加用户
* @param user
*/
void insertUser(User user);
/**
* 删除用户
* @param id
*/
void deleteUser(Integer id);
//**********************************************
/**
* 包装类查询用户
* @param queryvo
* @return
*/
User getUserByQueryVo(QueryVo queryvo);
/**
* 根据 用户名 和 性别查询用户
* @param user
* @return
*/
List<User> getUsersByQueryVo(User user);
/**
* 演示-foreach标签的使用,跟据用户id列表查询用户
* @param vo
* @return
*/
List<User> getUserByIds(QueryVo vo);
/**
* 演示一对多关联查询-ReaultMap
* @param user
* @return
*/
List<User> getUserOrderMap();
}
测试
package com.test;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import com.bo.Order;
import com.bo.QueryVo;
import com.bo.User;
import com.mapper.UserMapper;
import com.tuils.SqlSessionFactoryUtils;
public class UserMapperTest {
@Test
public void testGetUserById() {
SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession();
//获取接口的代理人实现类
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.getUserById(10);
System.out.println(user);
sqlSession.close();
}
//根据用户名查找用户
@Test
public void testGetUserByUserName() {
SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession();
//获取接口的代理人实现类
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = userMapper.getUserByUserName("张");
for(User user : userList) {
System.out.println(user);
}
//关闭sqlSession
sqlSession.close();
}
//根据用户名查找用户
@Test
public void testInsertUser() {
SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession();
//获取接口的代理人实现类
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setBirthday(new Date());
user.setAddress("阿拉斯加");
user.setSex("熊");
user.setUsername("熊二");
userMapper.insertUser(user);
System.out.println(user+"---------");
sqlSession.commit();
//关闭sqlSession
sqlSession.close();
}
//删除用户
@Test
public void deleteUser() {
SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession(true);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.deleteUser(31);
sqlSession.close();
}
//====================================================2=====================================
//简单的包装类
@Test
public void testQueryVoById() {
SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession();
//获取接口的代理人实现类
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
QueryVo queryvo = new QueryVo();
User user = new User();
user.setId(29);
queryvo.setUser(user);
User result_user = userMapper.getUserByQueryVo(queryvo);
System.out.println(result_user);
sqlSession.close();
}
// 多参数查询 根据用户名和性别查询
//
@Test
public void testQueryPojo() {
SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession();
//获取接口的代理人实现类
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//QueryVo queryvo = new QueryVo();
User user = new User();
user.setUsername("熊二");
user.setSex("熊");
// queryvo.setUser(user);
List<User> userList = userMapper.getUsersByQueryVo(user);
for(User user2 : userList) {
System.out.println(user2);
}
sqlSession.close();
}
//简单的包装类 ids ***** 参数为集合
@Test
public void testQueryVoByIds() {
SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession();
//获取接口的代理人实现类
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
QueryVo queryvo = new QueryVo();
//构建id列表
queryvo.setIds(Arrays.asList(1,10,16,24));
List<User> userList = userMapper.getUserByIds(queryvo);
for(User user2 : userList) {
System.out.println(user2);
}
sqlSession.close();
}
// 一对多
@Test
public void getUserOrderMap() {
SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession();
//获取接口的代理人实现类
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> list = userMapper.getUserOrderMap();
for (User user2 : list) {
System.out.println(user2);
for (Order order : user2.getOrders()) {
if(order.getId() != null){
System.out.println(" 此用户下的订单有:" + order);
}
}
}
sqlSession.close();
}
}