mybatis进阶

本文详细介绍了Mybatis的Dao层实现,包括传统开发方式和代理方式,并探讨了动态SQL的使用,如<if>、<where>、<foreach>标签以及SQL片段抽取。此外,还讲解了一对一、一对多和多对多的多表查询实现,通过<resultMap>配置映射关系。

1.Mybatis的Dao层实现

1.1 传统开发方式

1.1.1编写UserDao接口

public interface UserDao {

List<User> findAll() throws IOException;

}

1.1.2.编写UserDaoImpl实现

public class UserDaoImpl implements UserDao {

public List<User> findAll() throws IOException {

InputStream resourceAsStream =

Resources.getResourceAsStream("SqlMapConfig.xml");

SqlSessionFactory sqlSessionFactory = new

SqlSessionFactoryBuilder().build(resourceAsStream);

SqlSession sqlSession = sqlSessionFactory.openSession();

List<User> userList = sqlSession.selectList("userMapper.findAll");

sqlSession.close();

return userList;

}

}

1.1.3 测试传统方式

@Test

public void testTraditionDao() throws IOException {

UserDao userDao = new UserDaoImpl();

List<User> all = userDao.findAll();

System.out.println(all);

}

1.2 代理开发方式

1.2.1 代理开发方式介绍

采用 Mybatis 的代理开发方式实现 DAO 层的开发,这种方式是我们后面进入企业的主流。

Mapper 接口开发方法只需要程序员编写Mapper 接口(相当于Dao 接口),由Mybatis 框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。

Mapper 接口开发需要遵循以下规范:

1) Mapper.xml文件中的namespace与mapper接口的全限定名相同

2) Mapper接口方法名和Mapper.xml中定义的每个statement的id相同

3) Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql的parameterType的类型相同

4) Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同

1.2.2 编写UserMapper接口

1.2.3测试代理方式

@Test

public void testProxyDao() throws IOException {

InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");

SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);

SqlSession sqlSession = sqlSessionFactory.openSession();

//获得MyBatis框架生成的UserMapper接口的实现类

UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

User user = userMapper.findById(1);

System.out.println(user);

sqlSession.close();

}

1.3 知识小结

MyBatis的Dao层实现的两种方式:

手动对Dao进行实现:

传统开发方式

代理方式对Dao进行实现:

UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

 

2. 动态sql

动态sql语句概述

Mybatis 的映射文件中,前面我们的 SQL 都是比较简单的,有些时候业务逻辑复杂时,我们的 SQL是动态变化的,此时在前面的学习中我们的 SQL 就不能满足要求了。

     动态sql:sql语句是在程序运行期间动态生成的

    静态sql:sql语句是预先编写好的

 

<if>标签:

我们根据实体类的不同取值,使用不同的 SQL语句来进行查询。比如在 id如果不为空时可以根据id查询,如果username 不同空时还要加入用户名作为条件。这种情况在我们的多条件组合查询中经常会碰到。

    语法:

        <if test="条件表达式">

            sql语句信息

        </if>

 

<select id="findByCondition" parameterType="user" resultType="user">

    select * from User

    <where>

        <if test="id!=0">

            and id=#{id}

        </if>

        <if test="username!=null">

            and username=#{username}

        </if>

    </where>

</select>

    

<where>标签

    1. 如果第一个成立的条件前的关键字不是where,会自动修改成where

    2. 如果第一个成立的条件前没有where关键字,会自动添加where

    3. 如果没有任何条件成立,则sql后不会出现where关键字

    

<foreach>标签:

循环执行sql的拼接操作,例如:SELECT * FROM USER WHERE id IN (1,2,5)。

    语法:

        <foreach collection="list" open="id in(" close=")" item="id" separator=",">

                        #{id}

        </foreach>

 

<select id="findByIds" parameterType="list" resultType="user">

    select * from User

    <where>

        <foreach collection="array" open="id in(" close=")" item="id" separator=",">

            #{id}

        </foreach>

    </where>

</select>

 

foreach标签的属性含义如下:

<foreach>标签用于遍历集合

属性:

collection:代表要遍历的集合元素,注意编写时不要写#{}

open:代表语句的开始部分

close:代表结束部分

item:代表遍历集合的每个元素,生成的变量名

sperator:代表分隔符

    注意事项:

        1. #{}中的值必须和item属性的属性值保持一致

        2. 如果参数是List集合,collection属性有如下两个固定的可选属性值:

            list

            connection

        3. 如果参数是数组,collection属性值必须为array

SQL片段抽取

Sql 中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的

<!--抽取sql片段简化编写-->

<sql id="selectUser" select * from User</sql>

<select id="findById" parameterType="int" resultType="user">

    <include refid="selectUser"></include> where id=#{id}

</select>

<select id="findByIds" parameterType="list" resultType="user">

    <include refid="selectUser"></include>

    <where>

        <foreach collection="array" open="id in(" close=")" item="id" separator=",">

            #{id}

        </foreach>

    </where>

</select>

知识小结:

MyBatis映射文件配置:

<select>:查询

<insert>:插入

<update>:修改

<delete>:删除

<where>:where条件

<if>:if判断

<foreach>:循环

<sql>:sql片段抽取

 

3.PageHelper分页助手插件

    插件的概念:所谓的插件是第三方的开发者可以自己扩展mybaits的功能

    PageHelper插件的作用:用于简化分页操作

    使用步骤:

        1. 导入相关jar包

        2. 在核心配置文件中配置插件

            <plugins>

                <plugin interceptor="com.github.pagehelper.PageHelper">

                    <!--配置分页的方言,这样pagehelper才知道我们用的是什么类型的数据,该采用什么关键字实现分页-->

                    <property name="dialect" value="mysql"/>

                </plugin>

            </plugins>

        3. 在需要分页的查询操作之前指定分页的必有参数

             PageHelper.startPage(2,3);

                参数1:当前页码

                参数2:每页查询的记录数

        4. 调用查询方法

        5. 在得到查询的List集合之后,通过PageInfo对象包装结果,获取分页相关信息

        

        整体代码如下:

            @Test

            public void test1() throws Exception{

                // 设置分页的必有参数

                PageHelper.startPage(2,3);

                // 调用实现类的方法

                List<User> userList = userMapper.findAll();

                for (User user : userList) {

                    System.out.println(user);

                }

                // 获取分页相关数据

                PageInfo<User> pageInfo = new PageInfo<User>(userList);

                System.out.println("总记录数:"+pageInfo.getTotal());

                System.out.println("总页数:"+pageInfo.getPages());

                System.out.println("每页显示的记录数:"+pageInfo.getPageSize());

                System.out.println("当前页码:"+pageInfo.getPageNum());

            }

 

知识小结

MyBatis核心配置文件常用标签:

1、properties标签:该标签可以加载外部的properties文件

2、typeAliases标签:设置类型别名

3、environments标签:数据源环境配置标签

4、typeHandlers标签:配置自定义类型处理器

5、plugins标签:配置MyBatis的插件

 

4.Mybatis多表查询

 

1.1 一对一查询

1.1.1 一对一查询的模型

用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户

一对一查询的需求:查询一个订单,与此同时查询出该订单所属的用户

1.1.2一对一查询的语句

对应的sql语句:select * from orders o,user u where o.uid=u.id;

查询的结果如下:

1.1.3 创建Order和User实体

public class Order {

 

private int id;

private Date ordertime;

private double total;

 

//代表当前订单从属于哪一个客户

private User user;

}

 

public class User {

private int id;

private String username;

private String password;

private Date birthday;

 

}

1.1.4 创建OrderMapper接口

public interface OrderMapper {

List<Order> findAll();

}

1.1.5 配置OrderMapper.xml

<mapper namespace="com.itheima.mapper.OrderMapper">

<resultMap id="orderMap" type="com.itheima.domain.Order">

<result column="uid" property="user.id"></result>

<result column="username" property="user.username"></result>

<result column="password" property="user.password"></result>

<result column="birthday" property="user.birthday"></result>

</resultMap>

<select id="findAll" resultMap="orderMap">

select * from orders o,user u where o.uid=u.id

</select>

</mapper>

其中<resultMap>还可以配置如下:

<resultMap id="orderMap" type="com.itheima.domain.Order">

<result property="id" column="id"></result>

<result property="ordertime" column="ordertime"></result>

<result property="total" column="total"></result>

<association property="user" javaType="com.itheima.domain.User">

<result column="uid" property="id"></result>

<result column="username" property="username"></result>

<result column="password" property="password"></result>

<result column="birthday" property="birthday"></result>

</association>

</resultMap>

1.1.6 测试结果

OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);

List<Order> all = mapper.findAll();

for(Order order : all){

System.out.println(order);

}

1.2 一对多查询

1.2.1 一对多查询的模型

用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户

一对多查询的需求:查询一个用户,与此同时查询出该用户具有的订单

1.2.2 一对多查询的语句

对应的sql语句:select *,o.id oid from user u left join orders o on u.id=o.uid;

查询的结果如下:

1.2.3 修改User实体

public class Order {

 

private int id;

private Date ordertime;

private double total;

 

//代表当前订单从属于哪一个客户

private User user;

}

 

public class User {

private int id;

private String username;

private String password;

private Date birthday;

//代表当前用户具备哪些订单

private List<Order> orderList;

}

1.2.4 创建UserMapper接口

public interface UserMapper {

List<User> findAll();

}

1.2.5 配置UserMapper.xml

<mapper namespace="com.itheima.mapper.UserMapper">

<resultMap id="userMap" type="com.itheima.domain.User">

<result column="id" property="id"></result>

<result column="username" property="username"></result>

<result column="password" property="password"></result>

<result column="birthday" property="birthday"></result>

<collection property="orderList" ofType="com.itheima.domain.Order">

<result column="oid" property="id"></result>

<result column="ordertime" property="ordertime"></result>

<result column="total" property="total"></result>

</collection>

</resultMap>

<select id="findAll" resultMap="userMap">

select *,o.id oid from user u left join orders o on u.id=o.uid

</select>

</mapper>

1.2.6 测试结果

UserMapper mapper = sqlSession.getMapper(UserMapper.class);

List<User> all = mapper.findAll();

for(User user : all){

System.out.println(user.getUsername());

List<Order> orderList = user.getOrderList();

for(Order order : orderList){

System.out.println(order);

}

System.out.println("----------------------------------");

}

1.3 多对多查询

1.3.1 多对多查询的模型

用户表和角色表的关系为,一个用户有多个角色,一个角色被多个用户使用

多对多查询的需求:查询用户同时查询出该用户的所有角色

1.3.2 多对多查询的语句

对应的sql语句:select u.,r.,r.id rid from user u left join user_role ur on u.id=ur.user_id

inner join role r on ur.role_id=r.id;

查询的结果如下:

1.3.3 创建Role实体,修改User实体

public class User {

private int id;

private String username;

private String password;

private Date birthday;

//代表当前用户具备哪些订单

private List<Order> orderList;

//代表当前用户具备哪些角色

private List<Role> roleList;

}

 

public class Role {

 

private int id;

private String rolename;

 

}

1.3.4 添加UserMapper接口方法

List<User> findAllUserAndRole();

1.3.5 配置UserMapper.xml

<resultMap id="userRoleMap" type="com.itheima.domain.User">

<result column="id" property="id"></result>

<result column="username" property="username"></result>

<result column="password" property="password"></result>

<result column="birthday" property="birthday"></result>

<collection property="roleList" ofType="com.itheima.domain.Role">

<result column="rid" property="id"></result>

<result column="rolename" property="rolename"></result>

</collection>

</resultMap>

<select id="findAllUserAndRole" resultMap="userRoleMap">

select u.*,r.*,r.id rid from user u left join user_role ur on u.id=ur.user_id

inner join role r on ur.role_id=r.id

</select>

1.3.6 测试结果

UserMapper mapper = sqlSession.getMapper(UserMapper.class);

List<User> all = mapper.findAllUserAndRole();

for(User user : all){

System.out.println(user.getUsername());

List<Role> roleList = user.getRoleList();

for(Role role : roleList){

System.out.println(role);

}

System.out.println("----------------------------------");

}

1.4多表操作小结

多表模型分类:一对一、一对多、多对多。 

<resultMap>:配置字段和对象属性的映射关系标签。 

id 属性:唯一标识 

type 属性:实体对象类型 

<id>:配置主键映射关系标签。 

<result>:配置非主键映射关系标签。 

column 属性:表中字段名称 

property 属性: 实体对象变量名称 

<association>:配置被包含对象的映射关系标签。 

property 属性:被包含对象的变量名 

javaType 属性:被包含对象的数据类型 

<collection>:配置被包含集合对象的映射关系标签。 

property 属性:被包含集合对象的变量名 

ofType 属性:集合中保存的对象数据类型

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值