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

回顾

1. 嵌套查询
    将多表的联合,拆成多个单表查询,在通过mybatis嵌套组合
    步骤:一对一举例
        1)根据订单id查询订单
        2)根据订单uid查询用户
        3)最后由mybatis嵌套组合
2. 加载策略
    模型在关联时,是否要查询所管理的数据模型
    立即加载:一对一
    延迟加载:一对多、多对多

3. 缓存机制
    提高查询效率
    一级缓存:不需要我们做任何配置,底层就是map集合
    二级缓存:需要在映射文件配置 ,给实体类实现序列化接口【了解】

4. 核心配置文件回顾
    所有的配置文件,每一个标签必须加中文注释...

MyBatis注解&综合练习

今日目标

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

一 MyBatis注解

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

1.1 MyBatis常用注解

* @Insert:实现新增,代替了
 
* @Update:实现更新,代替了

* @Delete:实现删除,代替了

* @Select:实现查询,代替了

* @Result:实现结果集封装,代替了

* @Results:可以与@Result 一起使用,封装多个结果集,代替了

* @One:实现一对一结果集封装,代替了
 
* @Many:实现一对多结果集封装,代替了

环境搭建

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 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 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 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 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文件开启二级缓存的支持


    
    

在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

员工列表

② 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 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 findAll() {
        // 通过mybatis工具类获取sqlSession
        SqlSession sqlSession = MyBatisUtils.openSession();
        // 创建EmpDao代理对象
        EmpDao empDao = sqlSession.getMapper(EmpDao.class);
        // 查询
        List list= empDao.findAll();
        // 关闭sqlSession
        MyBatisUtils.close(sqlSession);
        return list;
    }
}

⑤ EmpDao(接口+映射)

1589340671696.png
1589341028132.png
1589341076131.png

⑥ list.jsp


    
        ${emp.id}
        ${emp.ename}
        ${emp.joindate}
        ${emp.salary}
        ${emp.address}
    

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 {
    
    private Integer totalCount; // 总记录数

    private Integer totalPage;// 总页数

    private List 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 pb = empService.findByPage(currentPage, pageSize);

        // 4.设置到request域
        request.setAttribute("pb", pb);

        // 5.转发
        request.getRequestDispatcher("/list.jsp").forward(request, response);
    }

④ EmpServiceImpl

@Override
public PageBean findByPage(int currentPage, int pageSize) {
    // 通过mybatis工具类获取sqlSession
    SqlSession sqlSession = MyBatisUtils.openSession();
    // 创建EmpDao代理对象
    EmpDao empDao = sqlSession.getMapper(EmpDao.class);

    // 1.创建 PageBean
    PageBean 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 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


        
姓名 性别 入职日期 薪资 住址
${emp.id} ${emp.ename} ${emp.joindate} ${emp.salary} ${emp.address}
总共检索到${pb.totalCount}条记录,共分${pb.totalPage}页
上一页 ${page} ${page} 下一页

总结

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

你可能感兴趣的:(5/13day53_注解&分页综合练习)