美文网首页
5/13day53_注解&分页综合练习

5/13day53_注解&分页综合练习

作者: 蹦蹦跶跶的起床啊 | 来源:发表于2020-05-15 22:24 被阅读0次

    回顾

    1. 嵌套查询
        将多表的联合,拆成多个单表查询,在通过mybatis嵌套组合
        步骤:一对一举例
            1)根据订单id查询订单
            2)根据订单uid查询用户
            3)最后由mybatis嵌套组合
    2. 加载策略
        模型在关联时,是否要查询所管理的数据模型
        立即加载:一对一
        延迟加载:一对多、多对多
    
    3. 缓存机制
        提高查询效率
        一级缓存:不需要我们做任何配置,底层就是map集合
        二级缓存:需要在映射文件配置<cache></cache> ,给实体类实现序列化接口【了解】
    
    4. 核心配置文件回顾
        所有的配置文件,每一个标签必须加中文注释...
    

    MyBatis注解&综合练习

    今日目标

    1. 注解开发
        单表【重点】
        多表【了解】
        
    2. 综合案例练习
        查询所有
        分页查询【重点:3遍】
    

    一 MyBatis注解

    ​ 这几年来注解开发越来越流行,Mybatis也可以使用注解开发方式,这样我们就可以减少编写Mapper映射文件了。我们先围绕一些基本的CRUD来学习,再学习复杂映射多表操作。

    1.1 MyBatis常用注解

    * @Insert:实现新增,代替了<insert></insert>
     
    * @Update:实现更新,代替了<update></update>
    
    * @Delete:实现删除,代替了<delete></delete>
    
    * @Select:实现查询,代替了<select></select>
    
    * @Result:实现结果集封装,代替了<result></result>
    
    * @Results:可以与@Result 一起使用,封装多个结果集,代替了<resultMap></resultMap>
    
    * @One:实现一对一结果集封装,代替了<association></association>
     
    * @Many:实现一对多结果集封装,代替了<collection></collection>
    

    环境搭建

    1589332825508.png

    1.2 MyBatis单表操作【重点】

    需求:基于user模块通过注解实现,增删改查

    ① UserMapper接口

    public interface UserMapper {
    
        // 查询所有
        @Select("select id as uid,username as uname,birthday as bir , sex as gender, address as addr from user")
        @Results({ // resultMap标签手动映射
                @Result(column = "uid",property = "id",id=true), // result标签映射封装
                @Result(column = "uname",property = "username"),
                @Result(column = "bir",property = "birthday"),
                @Result(column = "gender",property = "sex"),
                @Result(column = "addr",property = "address")
        })
        public List<User> findAll();
    
        // id查询
        @Select("select * from user where id = #{id}")
        public User findById(Integer id);
    
    
        // 新增
        @Insert("insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})")
        public void save(User user);
    
    
        // 修改(动态sql还是推荐使用xml)
        @Update("update user set username = #{username}, birthday = #{birthday}, sex = #{sex}, address = #{address} where id = #{id}")
        public void update(User user);
    
    
        // 删除
        @Delete("delete from user where id = #{id}")
        public void delete(Integer id);
    }
    

    ② 测试

    public class UserMapperTest extends BaseMapperTest {
    
        // 单表测试
        @Test
        public void test01() throws Exception {
            // 获取代理对象
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    
            // 查询所有
            List<User> list = userMapper.findAll();
            System.out.println(list);
    
           // 查询一个
           /* User user = userMapper.findById(41);
            System.out.println(user);*/
    
           // 新增
           /* User user = new User();
            user.setUsername("吉克隽逸");
            user.setBirthday(new Date());
            user.setSex("女");
            user.setAddress("彝族....");
    
            userMapper.save(user);*/
    
           // 更新
           /* User user = new User();
            user.setId(53);
            user.setUsername("迪丽热巴");
            user.setBirthday(new Date());
            user.setSex("女");
            user.setAddress("新疆....");
            userMapper.update(user);*/
    
    
           // 删除
           // userMapper.delete(53);
        }
    
    }
    

    1.3 MyBatis多表操作【了解】

    注解多表操作是基于嵌套查询来实现

    1589334124076.png

    1.3.1 一对一查询

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

    一对一查询语句

    SELECT * FROM orders where id = #{id};
    SELECT * FROM `user` WHERE id = #{订单的uid};
    

    ① OrderMapper接口

    public interface OrderMapper {
    
    
        // 一对一嵌套注解
        @Select("select * from orders where id = #{id}")
        @Results({
                @Result(column = "id",property = "id",id=true),
                @Result(column = "ordertime",property = "ordertime"),
                @Result(column = "money",property = "money")
        })
        public Order findByIdWithUser(Integer id);
    }
    

    ② UserMapper接口

    public interface UserMapper {
    
        // id查询
        @Select("select * from user where id = #{id}")
        public User findById(Integer id);
    }
    

    ③ 注解嵌套

    1589334818010.png

    ④ 测试

    public class OrderMapperTest extends BaseMapperTest { // 继承父类,就可以直接使用 父类的方法和成员变量了
    
        // 一对一嵌套测注解试
        @Test
        public void test01() throws Exception {
            // 获取代理对象
            OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
    
            // 根据id查询
            Order order = orderMapper.findByIdWithUser(1);
           System.out.println(order);
        }
    }
    

    1.3.2 一对多查询

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

    一对多查询语句

    SELECT * FROM `user` where id = #{id};
    SELECT * FROM orders where uid = #{用户id};
    

    ① UserMapper接口

    public interface UserMapper {
    
        // 一对多注解嵌套查询
        @Select("select * from user where id = #{id}")
        @Results({ // resultMap标签手动映射
                @Result(column = "id",property = "id",id=true), // result标签映射封装
                @Result(column = "username",property = "username"),
                @Result(column = "birthday",property = "birthday"),
                @Result(column = "sex",property = "sex"),
                @Result(column = "address",property = "address")
        })
        public User findByIdWithOrders(Integer id);
    }
    

    ② OrderMapper接口

    public interface OrderMapper {
       
        @Select("select * from orders where uid = #{id}")
        public List<Order> findByUid(Integer uid);
    }
    

    ③ 注解嵌套

    1589336198179.png

    ④ 测试

    // 一对多注解测试
    @Test
    public void test02() throws Exception {
        // 获取代理对象
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    
        User user = userMapper.findByIdWithOrders(41);
        System.out.println(user);
        System.out.println(user.getOrderList());
    }
    

    1.3.3 多对多查询

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

    多对多查询语句

    SELECT * FROM `user` where id = #{id};
    SELECT * FROM role r INNER JOIN user_role ur ON r.`id` = ur.`rid` 
        WHERE ur.`uid` = #{用户id};
    

    ① UserMapper接口

    public interface UserMapper {
    
    
        // 多对多注解嵌套查询
        @Select("select * from user where id = #{id}")
        @Results({ // resultMap标签手动映射
                @Result(column = "id",property = "id",id=true), // result标签映射封装
                @Result(column = "username",property = "username"),
                @Result(column = "birthday",property = "birthday"),
                @Result(column = "sex",property = "sex"),
                @Result(column = "address",property = "address")
        })
        public User findByIdWithRoles(Integer id);
    }
    

    ② RoleMapper接口

    public interface RoleMapper {
    
        
        @Select("SELECT * FROM role r INNER JOIN user_role ur ON ur.`rid` = r.`id` WHERE ur.`uid` =#{uid}")
        @Results({
                @Result(column = "id",property = "id",id=true),
                @Result(column = "role_name",property = "roleName"),
                @Result(column = "role_desc",property = "roleDesc")
        })
        public List<Role> findByUid(Integer uid);
    }
    

    ③ 注解嵌套

    1589336851156.png

    ④ 测试

    // 多对多注解测试
    @Test
    public void test03()throws Exception{
        // 获取代理对象
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    
        User user = userMapper.findByIdWithRoles(41);
        System.out.println(user);
        System.out.println(user.getRoleList());
    }
    

    1.4 局部延迟加载

    不管是一对多还是多对多 ,在注解配置中都有fetchType的属性

    * fetchType = FetchType.LAZY    表示懒加载
    
    * fetchType = FetchType.EAGER   表示立即加载
    
    * fetchType = FetchType.DEFAULT 表示使用全局配置
    

    1.5 二级缓存

    配置SqlMapConfig.xml文件开启二级缓存的支持

    <settings>
        <!--
            因为cacheEnabled的取值默认就为true,所以这一步可以省略不配置。
            为true代表开启二级缓存;为false代表不开启二级缓存。
        -->
        <setting name="cacheEnabled" value="true"/>
    </settings>
    

    在Mapper接口中使用注解配置二级缓存

    @CacheNamespace
    public interface UserMapper {...}
    
    1589337040594.png

    1.6 知识小结

    1. 注解开发和xml配置相比,从开发效率来说,注解编写更简单,效率更高。
    
    2. 从可维护性来说,注解如果要修改,必须修改源码,会导致维护成本增加。xml维护性更强。
    
    * 经验:单表简单CRUD可以使用注解、多表及动态sql你就用xml
    

    二 MyBatis案例练习

    2.1 编程风格

    浏览器:Chrome、Firefox

    包目录:cn(com).公司名.项目名(都是小写)

    类:大驼峰式命名

    方法名:小驼峰式命名

    帅哥用啥你用啥,帅哥写啥你写啥

    2.2 环境搭建

    ① 准备数据库和表

    1589337903879.png

    ② 创建web工程,导入jar包

    1589338008633.png

    ③ 导入页面资源

    1589338054431.png

    ④ 创建三层包结构

    1589338179795.png

    ⑤ 导入mybatis相关初始化配置

    1589338300300.png

    ⑥ 编写中文过滤器

    @WebFilter("/*")
    public class EncodeFilter implements Filter {
    
        public void init(FilterConfig config) throws ServletException {
    
        }
    
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws ServletException, IOException {
            // 接收请求字符集
            servletRequest.setCharacterEncoding("utf-8");
            
            // 放行
            chain.doFilter(servletRequest, servletResponse);
        }
    
        public void destroy() {
    
        }
    
    }
    

    ⑦ 测试环境

    2.3 查询所有

    2.3.1 需求和效果实现

    通过三层架构+接口+mybatis,查询员工信息,在页面展示

    1589339224995.png

    2.3.2 需求分析

    1589339710436.png

    2.3.3 代码实现

    1589340100662.png

    ① index.jsp

    <a href="${pageContext.request.contextPath}/EmpServlet?action=findAll">员工列表</a>
    

    ② Emp实体类

    public class Emp {
        
        private Integer id;
        
        private String ename;
        
        private String sex;
        
        private String joindate; // 通过字符串也可以表示日期
        
        private Double salary;
        
        private String address;
    }
    

    ③ EmpServlet

    @WebServlet("/EmpServlet")
    public class EmpServlet extends HttpServlet {
    
        // 重写service方法
        @Override
        protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 获取action请求参数
            String action = request.getParameter("action");
            // 判断
            if (action.equals("findAll")) {
                this.findAll(request, response);
            }
        }
    
        // 查询所有
        protected void findAll(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 1.调用service查询
            EmpService empService = new EmpServiceImpl();
            List<Emp> list = empService.findAll();
            // 2.将list写入request域
            request.setAttribute("list", list);
            // 3.转发
            request.getRequestDispatcher("/list.jsp").forward(request, response);
        }
    }
    

    ④ EmpServiceImpl

    public class EmpServiceImpl implements EmpService {
    
        @Override
        public List<Emp> findAll() {
            // 通过mybatis工具类获取sqlSession
            SqlSession sqlSession = MyBatisUtils.openSession();
            // 创建EmpDao代理对象
            EmpDao empDao = sqlSession.getMapper(EmpDao.class);
            // 查询
            List<Emp> list= empDao.findAll();
            // 关闭sqlSession
            MyBatisUtils.close(sqlSession);
            return list;
        }
    }
    

    ⑤ EmpDao(接口+映射)

    1589340671696.png 1589341028132.png 1589341076131.png

    ⑥ list.jsp

    <c:forEach items="${list}" var="emp">
        <tr>
            <td>${emp.id}</td>
            <td>${emp.ename}</td>
            <td>${emp.joindate}</td>
            <td>${emp.salary}</td>
            <td>${emp.address}</td>
        </tr>
    </c:forEach>
    

    2.4 分页查询【重点☆☆☆☆】

    2.4.1 导入数据

    insert  into `emp`(`id`,`ename`,`sex`,`joindate`,`salary`,`address`) values(6,'王昭君','女','2010-12-17',28500,'北京'),(7,'刘备','男','2014-07-18',24500,'广州'),(8,'小二郎','男','2004-11-23',30000,'广州'),(9,'小龙女','女','2009-05-18',50000,'深圳'),(10,'貂蝉','女','2014-07-30',15000,'深圳'),(11,'刘三','男','2019-06-23',11000,'上海'),(12,'李逵','男','2012-07-05',9500,'广州'),(13,'李楠','女','2012-07-05',11500,'北京'),(14,'小白龙','男','2011-09-18',30000,'深圳'),(15,'西施','女','2015-07-06',13000,'北京'),(16,'刘茹','女','2019-08-07',6000,'北京');
    

    2.4.2 分页介绍

    在实际开发中,如果数据库数据太多,一般我们需要进行分页查询,提高效率...

    分页技术实现

    物理分页:数据库实现(MySQL、Oracle)

    内存分页:查询全部,在通过java代码进行分页

    今天我们来使用MySQL操作物理分页

    * 语法:
            select * from 表名 limit 开始索引,每页个数;
            
    * 模拟百度分页,一个显示5条,数据库共有16条记录
        第一页
            select * from 表名 limit 0,5;
        第二页
            select * from 表名 limit 5,5;
        第三页
            select * from 表名 limit 10,5;
        第四页
            select * from 表名 limit 15,5;
            
    * 索引公式
            开始索引=(当前页-1) × 每页个数
            
    * 如何获得当前页和每页个数?
            前端页提供的
    

    2.4.3 需求和效果实现

    通过mysql物理分页,一个显示5条,数据库共有16条记录

    1589341995477.png

    2.4.3 需求分析

    1589342693907.png

    后端代码流程图

    1589350595261.png

    2.4.4 代码实现

    ① index.jsp

    1589350778119.png

    ② PageBean

    public class PageBean<E> {
        
        private Integer totalCount; // 总记录数
    
        private Integer totalPage;// 总页数
    
        private List<E> list; // 结果集
    
        private Integer currentPage; // 当前页
    
        private Integer pageSize; // 每页个数
    
    }
    

    ③ EmpServlet

    1589351273546.png
        EmpService empService = new EmpServiceImpl();
    
        // 分页查询
        protected void findByPage(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 1.接收请求参数
            String currentPageStr = request.getParameter("currentPage");
            String pageSizeStr = request.getParameter("pageSize");
    
            // 2.转为整型
            int currentPage = Integer.parseInt(currentPageStr);
            int pageSize = Integer.parseInt(pageSizeStr);
    
            // 3.调用service查询
            PageBean<Emp> pb = empService.findByPage(currentPage, pageSize);
    
            // 4.设置到request域
            request.setAttribute("pb", pb);
    
            // 5.转发
            request.getRequestDispatcher("/list.jsp").forward(request, response);
        }
    

    ④ EmpServiceImpl

    @Override
    public PageBean<Emp> findByPage(int currentPage, int pageSize) {
        // 通过mybatis工具类获取sqlSession
        SqlSession sqlSession = MyBatisUtils.openSession();
        // 创建EmpDao代理对象
        EmpDao empDao = sqlSession.getMapper(EmpDao.class);
    
        // 1.创建 PageBean
        PageBean<Emp> pageBean = new PageBean<>();
    
        // 2.封装当前页和每页个数
        pageBean.setCurrentPage(currentPage);
        pageBean.setPageSize(pageSize);
    
        // 3.调用dao查询总记录数并封装
        Integer totalCount = empDao.findCount();
        pageBean.setTotalCount(totalCount);
    
        // 4.计算并封装总页数
        int totalPage = (int)Math.ceil(totalCount * 1.0/ pageSize);
        pageBean.setTotalPage(totalPage);
    
        // 5.计算开始索引
        int index = (currentPage - 1) * pageSize;
    
        // 6.调用dao查询结果集并封装
        List<Emp> list = empDao.findList(index,pageSize);
        pageBean.setList(list);
        // 关闭sqlSession
        MyBatisUtils.close(sqlSession);
        // 7.返回pageBean对象
        return pageBean;
    }
    

    ⑤ EmpDao(接口+映射)

    1589352386073.png 1589352398163.png

    ⑥ list.jsp

    1589352796689.png
    <body>
    <table border="1" cellpadding="0" cellspacing="0" width="600px">
        <tr>
            <td>姓名</td>
            <td>性别</td>
            <td>入职日期</td>
            <td>薪资</td>
            <td>住址</td>
        </tr>
        <c:forEach items="${pb.list}" var="emp">
            <tr>
                <td>${emp.id}</td>
                <td>${emp.ename}</td>
                <td>${emp.joindate}</td>
                <td>${emp.salary}</td>
                <td>${emp.address}</td>
            </tr>
        </c:forEach>
    </table>
    <table>
        <tr>
            <td style="text-align: left">总共检索到${pb.totalCount}条记录,共分${pb.totalPage}页</td>
        </tr>
    </table>
    <table id="page">
        <tr>
                <c:if test="${pb.currentPage>1}">
                     <td style="width:50px">
                        <a style="text-decoration: none" href="${pageContext.request.contextPath}/EmpServlet?action=findByPage&currentPage=${pb.currentPage-1}&pageSize=5">上一页</a>
                    </td>
                </c:if>
            <c:forEach begin="1" end="${pb.totalPage}" var="page">
                <c:if test="${page == pb.currentPage}">
                    <td bgcolor="#ffd700">
                        <a style="text-decoration: none" href="${pageContext.request.contextPath}/EmpServlet?action=findByPage&currentPage=${page}&pageSize=5">${page}</a>
                    </td>
                </c:if>
                <c:if test="${page != pb.currentPage}">
                    <td>
                        <a style="text-decoration: none" href="${pageContext.request.contextPath}/EmpServlet?action=findByPage&currentPage=${page}&pageSize=5">${page}</a>
                    </td>
                </c:if>
    
            </c:forEach>
            <c:if test="${pb.currentPage < pb.totalPage}">
                <td style="width:50px">
                    <a style="text-decoration: none" href="${pageContext.request.contextPath}/EmpServlet?action=findByPage&currentPage=${pb.currentPage+1}&pageSize=5">下一页</a>
                </td>
            </c:if>
        </tr>
    </table>
    </body>
    

    总结

    1. mybatis注解  晚上敲
        单表【重点】
            @Insert
            @Update
            @Delete
            @Select
            @Results
            @Result
        多表【休息日再敲....】
        
    2. 综合案例  下午敲
        编程风格(跟帅哥一致...)
        环境搭建
        查询所有
        JDBC
        
        分页查询【晚上敲】
        
        
    3. 明天课程非常轻松...
    

    相关文章

      网友评论

          本文标题:5/13day53_注解&分页综合练习

          本文链接:https://www.haomeiwen.com/subject/pqqkohtx.html