Mybatis Dao开发方式
5.1Dao需求
根据用户ID查询用户信息
根据用户名查找用户列表
添加用户
5.2原始Dao开发方法
5.2.1使用原有的user映射文件,不需修改
5.2.2新建个UserDao接口
public interface UserDao {
/**根据用户ID查询用户信息
* @param id
* @return
*/
User getUserById(Integer id);
/**
* 根据用户名查找用户列表
* @param name
* @return
*/
List<User> getUserByUserName(String name);
/**
* 添加用户
* @param user
*/
void insertUser(User user);
}
5.2.3新建个UserDaoImpl接口实现类
public class UserDaoImpl implements UserDao {
@Override
public User getUserById(Integer id) {
SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession();
User user = sqlSession.selectOne("user.getUserById", id);
sqlSession.close();
return user;
}
@Override
public List<User> getUserByUserName(String name) {
SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession();
List<User> list = sqlSession.selectList("user.getUserByName", name);
sqlSession.close();
return list;
}
@Override
public void insertUser(User user) {
SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession();
sqlSession.insert("user.insertUser", user);
sqlSession.commit();
sqlSession.close();
}
}
5.2.4使用dao测试
public class UserDaoTest {
@Test
public void testGetUserById() {
UserDao userDao = new UserDaoImpl();
User user = userDao.getUserById(30);
System.out.println(user);
}
@Test
public void testGetUserByUserName() {
UserDao userDao = new UserDaoImpl();
List<User> list = userDao.getUserByUserName("张");
for (User user : list) {
System.out.println(user);
}
}
@Test
public void testInsertUser() {
UserDao userDao = new UserDaoImpl();
User user = new User();
user.setUsername("张飞3");
user.setAddress("深圳市");
user.setBirthday(new Date());
user.setSex("1");
userDao.insertUser(user);
}
}
5.3官方推荐,接口动态代理
5.3.1动态代理dao开发规则
1.namespace必需是接口的全路径名
2.接口的方法名必需与映射文件的sql id一致
3.接口的输入参数必需与映射文件的parameterType类型一致
4.接口的返回类型必须与映射文件的resultType类型一致
5.3.2动态代理dao开发步骤
1.创建UserMapper.xml映射文件(把原来的user.xml复制按开发规则要求修改一下)
2.创建UserMapper接口(把原来的UserDao.java复制按开发规则要求修改一下)
3.加载UserMapper.xml4.测试动态代理Dao
public class UserMapperTest {
@Test
public void testGetUserById() {
// 加载配置得到SqlSession
SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession();
// 获取代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 查询数据
User user = userMapper.getUserById(30);
System.out.println(user);
// 关闭资源
sqlSession.close();
}
@Test
public void testGetUserByUserName() {
SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession();
// 获取代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 查询数据
List<User> list = userMapper.getUserByName("张");
for (User user : list) {
System.out.println(user);
}
// 关闭资源
sqlSession.close();
}
@Test
public void testInsertUser() {
SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSessionFactory().openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setUsername("张飞飞");
user.setAddress("深圳市黑马");
user.setBirthday(new Date());
user.setSex("1");
userMapper.insertUser(user);
// 提交事务
sqlSession.commit();
// 关闭资源
sqlSession.close();
}
}
6SqlMapConf.xml配置
6.1properties
6.1.1属性核心文件配置
6.1.2jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root
6.2typeAliases
mybatis默认支持java基本数据类型的别名识别详细参考教案。
自定义别名
<typeAliases>
<!-- 单个别名定义 -->
<!-- <typeAlias type="com.itheima.mybatis.pojo.User" alias="user"/> -->
<!-- 别名包扫描器(推荐使用此方式),整个包下的类都被定义别名,别名为类名,不区分大小写-->
<package name="com.itheima.mybatis.pojo"/>
</typeAliases>
6.3mappers
<mappers>
<!-- 第一种方式,加载 resource-->
<mapper resource="mapper/user.xml"/>
<!-- <mapper resource="mapper/UserMapper.xml"/> -->
<!-- 第二种方式,class扫描器要求:
1、映射文件与接口同一目录下
2、映射文件名必需与接口文件名称一致
-->
<!-- <mapper class="com.itheima.mybatis.mapper.UserMapper"/> -->
<!-- 第三种方式,包扫描器要求(推荐使用此方式):
1、映射文件与接口同一目录下
2、映射文件名必需与接口文件名称一致
-->
<package name="com.itheima.mybatis.mapper"/>
</mappers>
2输入映射和输出映射
2.1parameterType(输入类型)
Mybatis使用ognl表达式解析对象字段的值,#{}或者${}括号中的值为pojo属性名称。
2.1.3传递pojo包装对象
- 新建包装pojo对象QueryVo
/**
* 包装pojo
* @author Steven
*/
public class QueryVo {
//用户对象
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
- 映射文件与sql
<!-- 1、resultType:如果要返回数据集合,只需设定为每一个元素的数据类型
2、 包装的pojo取值通过 "."来获取
-->
<select id="getUserByQueryVo" parameterType="queryvo" resultType="com.itheima.mybatis.pojo.User">
<!-- SELECT * FROM USER WHERE username LIKE #{name} -->
SELECT * FROM USER WHERE username LIKE '%${user.username}%'
</select>
- 新增接口方法
- 增加测试方法,完成测试
2.2resultType(输出类型)
2.2.1输出简单类型
<!-- 查询用户总记录数,演示返回简单类型 -->
<select id="getUserCount" resultType="int">
SELECT COUNT(1) FROM USER
</select>
其它步骤跟前面类似,添加接口方法与测试方法,完成测试。
2.2.2输出pojo对象
参考第一天内容
2.2.3输出pojo列表
参考第一天内容。
2.3输出resultMap
演示基于完成订单列表的查询,由user_id字段与pojo属性不一致时引出的resultMap。
<!-- resultMap入门
type:映射成的pojo类型
id:resultMap唯一标识
-->
<resultMap type="order" id="orderMap">
<!-- id标签用于绑定主键 -->
<!-- <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="getOrderListResultMap" resultMap="orderMap">
SELECT * FROM `order`
</select>
其它步骤跟前面类似,添加接口方法与测试方法,完成测试。
3动态sql
3.1If
演示基于完成用户列表查询功能,由多查询条件拼装引出if标签。
<!-- 演示动态sql-if标签的使用情景 -->
<select id="getUserByWhere" parameterType="user" resultType="com.itheima.mybatis.pojo.User">
<!-- SELECT * FROM USER WHERE username LIKE '%${username}%' and id = #{id} -->
SELECT * FROM USER where 1 = 1
<!-- if标签的使用 -->
<if test="id != null">
and id = #{id}
</if>
<if test="username != null and username != ''">
and username LIKE '%${username}%'
</if>
</select>
其它步骤跟前面类似,添加接口方法与测试方法,完成测试。
3.2Where
复制getUserByWhere修改一下,改名为getUserByWhere2。
<!-- 演示动态sql-where标签的使用情景 -->
<select id="getUserByWhere2" parameterType="user"
resultType="com.itheima.mybatis.pojo.User">
<!-- include:引入sql片段,refid引入片段id -->
SELECT
*
FROM USER
<!-- where会自动加上where同处理多余的and -->
<where>
<!-- if标签的使用 -->
<if test="id != null">
and id = #{id}
</if>
<if test="username != null and username != ''">
and username LIKE '%${username}%'
</if>
</where>
</select>
其它步骤跟前面类似,添加接口方法与测试方法,完成测试。
3.3 Foreach
复制getUserByWhere2修改一下,改名为getUserByIds。
<!-- 演示动态sql-foreach标签的使用情景 -->
<select id="getUserByIds" parameterType="queryvo"
resultType="com.itheima.mybatis.pojo.User">
SELECT
*
FROM USER
<!-- where会自动加上where同处理多余的and -->
<where>
<!-- id IN(1,10,25,30,34) -->
<!-- foreach循环标签
collection:要遍历的集合,来源入参
open:循环开始前的sql
separator:分隔符
close:循环结束拼接的sql
-->
<foreach item="uid" collection="ids" open="id IN(" separator=","
close=")">
#{uid}
</foreach> </where>
</select>
其它步骤跟前面类似,添加接口方法与测试方法,完成测试。
3.4Sql片段
演示通过select * 不好引出查询字段名,抽取共用sql片段。
- 定义
<sql id="user_column">
`id`,
`username`,
`birthday`,
`sex`,
`address`,
`uuid2`
</sql>
- 使用
SELECT
FROM USER
其它步骤跟前面类似,添加接口方法与测试方法,完成测试。
4关联查询
4.1一对一关联
4.1.1方法一,使用resultType
-
新建OrderUser的pojo,继承自Order。
public class OrderUser extends Order {private String username;
private String address;
…….get,set
} -
修改order的映射文件,新增查询方法getOrderUser。
<select id="getOrderUser" resultType="orderuser">
SELECT
o.`id`,
o.`user_id` userId,
o.`number`,
o.`createtime`,
o.`note`,
u.`username`,
u.`address`
FROM `order` o
LEFT JOIN `user` u
ON u.id = o.`user_id`
</select>
其它步骤跟前面类似,添加接口方法与测试方法,完成测试。
4.1.2方法二,使用resultMap
-
改造order的pojo
-
修改order的映射文件
<resultMap type="order" id="order_user_map">
<!-- id标签用于绑定主键 -->
<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"/>
<!-- association:配置一对一关联
property:绑定的用户属性
javaType:属性数据类型,支持别名
-->
<association property="user" javaType="com.itheima.mybatis.pojo.User">
<id property="id" column="user_id"/>
<result property="username" column="username"/>
<result property="address" column="address"/>
<result property="sex" column="sex"/>
</association>
</resultMap>
<!-- 一对一关联查询-使用resultMap -->
<select id="getOrderUser2" resultMap="order_user_map">
SELECT
o.`id`,
o.`user_id`,
o.`number`,
o.`createtime`,
o.`note`,
u.`username`,
u.`address`,
u.`sex`
FROM `order` o
LEFT JOIN `user` u
ON u.id = o.`user_id`
</select>
其它步骤跟前面类似,添加接口方法与测试方法,完成测试。
4.2一对多关联
-
改造user的pojo
-
修改user的映射文件
<resultMap type="user" id="user_order_map">
<id property="id" column="id" />
<result property="username" column="username" />
<result property="birthday" column="birthday" />
<result property="address" column="address" />
<result property="sex" column="sex" />
<result property="uuid2" column="uuid2" />
<!-- collection:配置一对多关系
property:用户下的order属性
ofType:property的数据类型,支持别名
-->
<collection property="orders" ofType="order">
<!-- id标签用于绑定主键 -->
<id property="id" column="oid"/>
<!-- 使用result绑定普通字段 -->
<result property="userId" column="id"/>
<result property="number" column="number"/>
<result property="createtime" column="createtime"/>
</collection>
</resultMap>
<!-- 一对多关联查询 -->
<select id="getUserOrder" resultMap="user_order_map">
SELECT
u.`id`,
u.`username`,
u.`birthday`,
u.`sex`,
u.`address`,
u.`uuid2`,
o.`id` oid,
o.`number`,
o.`createtime`
FROM `user` u
LEFT JOIN `order` o
ON o.`user_id` = u.`id`
</select>