day2021/9/28mybatis多对多,分页查询,通用mapper

第三天课程结束,多对多,通用mapper让我体会到代码不断的被简化,感谢前辈的贡献。
多对多符合现实场景,万物之间都是有关联的,都是多个对多个的关系。

6.关联查询:多对多

6.1 学生和老师数据模型

6.1.1 表间关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rsaQAZGk-1632788039797)(assets/image-20210721145256539.png)]

#老师表
CREATE TABLE teacher(
 tid INT PRIMARY KEY,
 NAME VARCHAR(50)
); 
#学生表
CREATE TABLE student(
 sid INT PRIMARY KEY,
 NAME VARCHAR(50)
);
#中间表
CREATE TABLE teacher_student(
 teacher_id INT ,
 student_id INT,
 CONSTRAINT ts_t_fk FOREIGN KEY (teacher_id) REFERENCES teacher(tid),
 CONSTRAINT ts_s_fk FOREIGN KEY (student_id) REFERENCES student(sid)
);

INSERT INTO teacher VALUES (1,'肖老师'); 
INSERT INTO teacher VALUES (2,'马老师'); 

INSERT INTO student VALUES (1,'张三');
INSERT INTO student VALUES (2,'李四');
INSERT INTO student VALUES (3,'王五');

INSERT INTO teacher_student VALUES (1,1);
INSERT INTO teacher_student VALUES (1,2);
INSERT INTO teacher_student VALUES (1,3);
INSERT INTO teacher_student VALUES (2,1);
INSERT INTO teacher_student VALUES (2,2);

6.1.2 JavaBean及其关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sWRet8On-1632788039802)(assets/image-20210721145855505.png)]

  • JavaBean:Student

    package com.czxy.ssm.domain;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * #学生表
     * CREATE TABLE student(
     *  sid INT PRIMARY KEY,
     *  NAME VARCHAR(50)
     * );
     * @author 桐叔
     * @email liangtong@itcast.cn
     */
    public class Student {
        private Integer sid;
        private String name;
    
        private List<Teacher> teacherList = new ArrayList<>();
    
        public Integer getSid() {
            return sid;
        }
    
        public void setSid(Integer sid) {
            this.sid = sid;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public List<Teacher> getTeacherList() {
            return teacherList;
        }
    
        public void setTeacherList(List<Teacher> teacherList) {
            this.teacherList = teacherList;
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "sid=" + sid +
                    ", name='" + name + '\'' +
                    ", teacherList=" + teacherList +
                    '}';
        }
    }
    
  • JavaBean:Teacher

    package com.czxy.ssm.domain;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * #老师表
     * CREATE TABLE teacher(
     *  tid INT PRIMARY KEY,
     *  NAME VARCHAR(50)
     * );
     * @author 桐叔
     * @email liangtong@itcast.cn
     */
    public class Teacher {
        private Integer tid;
        private String name;
    
        private List<Student> studentList = new ArrayList<>();
    
        public Integer getTid() {
            return tid;
        }
    
        public void setTid(Integer tid) {
            this.tid = tid;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public List<Student> getStudentList() {
            return studentList;
        }
    
        public void setStudentList(List<Student> studentList) {
            this.studentList = studentList;
        }
    
        @Override
        public String toString() {
            return "Teacher{" +
                    "tid=" + tid +
                    ", name='" + name + '\'' +
                    ", studentList=" + studentList +
                    '}';
        }
    }
    
    

6.2 多对多:老师–>学生

  • 需要根据老师tid查询中间表中,对应的所有学生id

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q5jllkRi-1632788039812)(assets/image-20210721155108930.png)]

6.2.1 student 映射

package com.czxy.ssm.mapper;

import com.czxy.ssm.domain.Student;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
public interface StudentMapper {
    /**
     * 通过tid查询对应的学生
     * @param tid
     * @return
     * @throws Exception
     */
    @Select("select * from student s where s.sid in (select student_id from teacher_student where teacher_id = #{tid} )")
    public Student findStudentByTeacherId(@Param("tid") Integer tid) throws Exception;
}

6.2.2 teacher 映射

package com.czxy.ssm.mapper;

import com.czxy.ssm.domain.Teacher;
import org.apache.ibatis.annotations.*;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
public interface TeacherMapper {

    @Select("select * from teacher t where  t.tid = #{tid}")
    @Results({
            @Result(property="tid" , column="tid"),
            @Result(property="name" , column="name"),
            @Result(property="studentList" , many=@Many(select="com.czxy.ssm.mapper.StudentMapper.findStudentByTeacherId") , column="tid"),
    })
    public Teacher selectById(@Param("tid") Integer tid);

}

6.2.3 测试

package com.czxy.ssm.test;

import com.czxy.ssm.domain.Order;
import com.czxy.ssm.domain.Teacher;
import com.czxy.ssm.mapper.OrderMapper;
import com.czxy.ssm.mapper.TeacherMapper;
import com.czxy.ssm.utils.MyBatisUtils;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
public class Test09_SelectTeacher {
    public static void main(String[] args) {
        TeacherMapper teacherMapper = MyBatisUtils.getMapper(TeacherMapper.class);

        Teacher teacher = teacherMapper.selectById(1);
        // 打印
        System.out.println(teacher);

        MyBatisUtils.commitAndclose();
    }
}

6.2.4 巩固练习

  • 查询所有的老师,并查询老师对应的学生。

    package com.czxy.ssm.mapper;
    
    import com.czxy.ssm.domain.Teacher;
    import org.apache.ibatis.annotations.*;
    
    import java.util.List;
    
    /**
     * @author 桐叔
     * @email liangtong@itcast.cn
     */
    public interface TeacherMapper {
    
        /**
         * 通过id查询详情
         * @param tid
         * @return
         */
        @Select("select * from teacher t where  t.tid = #{tid}")
        @Results(id = "teacherResult" , value = {
                @Result(property="tid" , column="tid"),
                @Result(property="name" , column="name"),
                @Result(property="studentList" , many=@Many(select="com.czxy.ssm.mapper.StudentMapper.findStudentByTeacherId") , column="tid"),
        })
        public Teacher selectById(@Param("tid") Integer tid);
    
        /**
         * 查询所有
         * @return
         */
        @Select("select * from teacher")
        @ResultMap("teacherResult")
        public List<Teacher> selectList();
    
    }
    
  • 测试类

    package com.czxy.ssm.test;
    
    import com.czxy.ssm.domain.Teacher;
    import com.czxy.ssm.mapper.TeacherMapper;
    import com.czxy.ssm.utils.MyBatisUtils;
    
    import java.util.List;
    
    /**
     * @author 桐叔
     * @email liangtong@itcast.cn
     */
    public class Test10_SelectAllTeacher {
        public static void main(String[] args) {
            TeacherMapper teacherMapper = MyBatisUtils.getMapper(TeacherMapper.class);
    
            List<Teacher> teacherList = teacherMapper.selectList();
            // 打印
            teacherList.forEach(teacher -> {
                System.out.println(teacher);
            });
    
            MyBatisUtils.commitAndclose();
        }
    }
    

7.分页查询

MyBatis没有提供分页支持,需要自己编写limit语句。

开发中我们采用PageHelper插件。

7.1 搭建环境

7.1.1 导入jar包

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GgqMakI9-1632788039814)(assets/image-20210721161056976.png)]

7.1.2 添加插件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IvmWya7i-1632788039815)(assets/image-20210721161328679.png)]

	<!-- 插件 -->
	<plugins>
		<plugin interceptor="com.github.pagehelper.PageHelper">
			<!-- 方言 -->
			<property name="dialect" value="mysql"/>
			<!-- 设置为true时,使用RowBounds分页会进行count查询 -->
			<property name="rowBoundsWithCount" value="true"/>
		</plugin>
	</plugins>

7.2 语法

1) 设置分页数据
PageHelper.startPage(int pageNum, int pageSize)
	参数1:pageNum 第几页
	参数2:pageSize 页面显示个数
2) 封装分页结果 PageInfo
	new PageInfo(查询结果)	  //创建分页对象
	pageInfo.getTotal(),	//自动查询总条数
	pageInfo.getPages(),	//总分页数

7.3 使用

package com.czxy.ssm.test;

import com.czxy.ssm.domain.Teacher;
import com.czxy.ssm.domain.User;
import com.czxy.ssm.mapper.TeacherMapper;
import com.czxy.ssm.mapper.UserMapper;
import com.czxy.ssm.utils.MyBatisUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import java.util.List;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
public class Test11_Page {
    public static void main(String[] args) {
        UserMapper userMapper = MyBatisUtils.getMapper(UserMapper.class);

        // 设置分页 **
        PageHelper.startPage(1,2);

        // 查询
        List<User> users = userMapper.selectAll();

        // 获得封装对象 ** 
        PageInfo<User> pageInfo = new PageInfo<>(users);

        // 打印分页信息
        long total = pageInfo.getTotal();
        List<User> list = pageInfo.getList();
        System.out.println("总条数:" + total);
        System.out.println("分页数据:");
        list.forEach(user -> {
            System.out.println(user);
        });


        MyBatisUtils.commitAndclose();
    }
}

8. 通用Mapper

8.1 概述

  • 通用Mapper对MyBatis进行简化的第三方工具包。

  • 通用Mapper提供了一个名为Mapper<T>的接口,用于自动完成单表的增删改查操作。

public interface UserMapper extends Mapper<User> {
}
  • 如果通用Mapper中的方法不足以满足你的需求,直接添加自定义方法即可。

8.2 搭建环境

8.2.1 导入jar

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cthmBtcG-1632788039816)(assets/image-20210721173357517.png)]

8.2.2 修改工具类

  • 添加内容从官方文档中拷贝
package com.czxy.ssm.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.common.MySqlMapper;
import tk.mybatis.mapper.entity.Config;
import tk.mybatis.mapper.mapperhelper.MapperHelper;

import java.io.InputStream;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
public class MyBatisUtils {

    // 会话工厂
    private static SqlSessionFactory factory;
    static{
        try {
            // 1.1 加载核心配置文件
            InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
            // 1.2 获得工厂
            factory = new SqlSessionFactoryBuilder().build(is);

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static ThreadLocal<SqlSession> local = new ThreadLocal<>();

    /**
     * 获得新会话
     * @return
     */
    private static SqlSession openSession(){
        SqlSession sqlSession = local.get();
        if(sqlSession == null){
            sqlSession = factory.openSession();

            //创建一个MapperHelper
            MapperHelper mapperHelper = new MapperHelper();
            //特殊配置
            Config config = new Config();
            // 设置UUID生成策略
            // 配置UUID生成策略需要使用OGNL表达式
            // 默认值32位长度:@java.util.UUID@randomUUID().toString().replace("-", "")
            //config.setUUID("");
            // 主键自增回写方法,默认值MYSQL,详细说明请看文档
//	        config.setIDENTITY("HSQLDB");
            // 支持方法上的注解
            // 3.3.1版本增加
            config.setEnableMethodAnnotation(true);
            config.setNotEmpty(true);
            // 序列的获取规则,使用{num}格式化参数,默认值为{0}.nextval,针对Oracle
            // 可选参数一共3个,对应0,1,2,分别为SequenceName,ColumnName, PropertyName
            //config.setSeqFormat("NEXT VALUE FOR {0}");
            // 设置全局的catalog,默认为空,如果设置了值,操作表时的sql会是catalog.tablename
            //config.setCatalog("");
            // 设置全局的schema,默认为空,如果设置了值,操作表时的sql会是schema.tablename
            // 如果同时设置了catalog,优先使用catalog.tablename
            //config.setSchema("");
            // 主键自增回写方法执行顺序,默认AFTER,可选值为(BEFORE|AFTER)
            //config.setOrder("AFTER");
            //设置配置
            mapperHelper.setConfig(config);
            // 注册通用tk.mybatis.mapper.common.Mapper接口 - 可以自动注册继承的接口
            mapperHelper.registerMapper(Mapper.class);
            mapperHelper.registerMapper(MySqlMapper.class);
//	        mapperHelper.registerMapper(SqlServerMapper.class);
//	        mapperHelper.registerMapper(IdsMapper.class);
            //配置完成后,执行下面的操作
            mapperHelper.processConfiguration(sqlSession.getConfiguration());


            local.set(sqlSession);
        }
        return sqlSession;
    }

    /**
     * 获得mapper
     * @param clazz
     * @return
     */
    public static <T> T getMapper(Class<T> clazz){
        return openSession().getMapper(clazz);
    }

    /**
     * 释放资源
     */
    public static void close() {
        SqlSession sqlSession = openSession();
        if(sqlSession != null){
            sqlSession.close();
        }
    }

    /**
     * 提交并释放资源
     */
    public static void commitAndclose() {
        SqlSession sqlSession = openSession();
        if(sqlSession != null){
            sqlSession.commit();
            close();
        }
    }

    /**
     * 回滚并释放资源
     */
    public static void rollbackAndclose() {
        SqlSession sqlSession = openSession();
        if(sqlSession != null){
            sqlSession.rollback();
            close();
        }
    }

}

8.3 编写Mapper

  • 编写接口,继承tk.mybatis.mapper.common.Mapper接口即可
    • 注意:Mapper接口以tk开头
package com.czxy.ssm.mapper;

import com.czxy.ssm.domain.User;
import tk.mybatis.mapper.common.Mapper;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
public interface UserMapper2 extends Mapper<User> {
}

8.4 通用API

  • 查询方法

    方法名描述
    T selectOne(T t)根据实体中的属性进行查询,只能有一个返回值,有多个结果是抛出异常,查询条件使用等号
    List select(T t)根据实体中的属性值进行查询,查询条件使用等号
    List selectAll()查询全部结果
    int selectCount(T t)根据实体中的属性查询总数,查询条件,使用等号
    T selectByPrimaryKey(Object key)根据主键字段进行查询
    boolean existsWhithPrimaryKey(Object key)根据主键字段查询记录是否存在
    List selectByExample(Object example)根据Example条件进行查询
    T selectOneByExample(Object example)根据Example条件进行查询,只能有一个返回值
    int selectCountByExample(Object example)根据Example条件进行查询记录数
  • 插入方法

    方法名描述
    int insert(T t)保存一个实体,null的属性也会保存,不会使用数据库默认值
    int intsertSelective(T t)保存一个实体,null的属性不会保存,使用数据库默认值
  • 更新方法

    方法名描述
    int updateByPrimaryKey(T t)根据主键更新实体全部字段,null值会被更新
    int updateByPrimaryKeySelective(T t)根据主键更新实体中不为null值的字段
  • 删除方法

    方法名描述
    int delete(T t)根据实体属性作为条件进行删除,查询条件使用等号
    int deletePrimaryKey(Object key)根据主键字段进行删除
    int deleteByExample(Object example)根据Example条件删除数据

8.4.1 通过主键查询

  • 1)确定主键,否则所有字段都是主键

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NNPDBIdk-1632788039817)(assets/image-20210721173445273.png)]

  • 2)测试

    package com.czxy.ssm.test;
    
    import com.czxy.ssm.domain.User;
    import com.czxy.ssm.mapper.UserMapper;
    import com.czxy.ssm.mapper.UserMapper2;
    import com.czxy.ssm.utils.MyBatisUtils;
    import org.junit.Test;
    
    import java.io.IOException;
    import java.util.List;
    
    /**
     * @author 桐叔
     * @email liangtong@itcast.cn
     */
    public class Test13_Mapper {
        @Test
        public void testSelectByPrimaryKey() {
            UserMapper2 userMapper2 = MyBatisUtils.getMapper(UserMapper2.class);
            User user = userMapper2.selectByPrimaryKey("1");
            System.out.println(user);
    
            MyBatisUtils.commitAndclose();
    
        }
    }
    

8.4.2 查询所有

    @Test
    public void testSelectAll() {
        UserMapper2 userMapper2 = MyBatisUtils.getMapper(UserMapper2.class);
        List<User> list = userMapper2.selectAll();
        // 打印
        list.forEach(System.out::println);

        MyBatisUtils.commitAndclose();
    }

8.4.3 添加

@Test
    public void testInsert() {
        UserMapper2 userMapper2 = MyBatisUtils.getMapper(UserMapper2.class);

        User user = new User();
        user.setUid("2");
        user.setUsername("jack");
        user.setPassword("1234");
        user.setName("杰克");
        user.setEmail("itcast_lt@163.com");
        user.setBirthday(new Date());
        user.setSex("男");
        user.setSex("0");

        int result = userMapper2.insert(user);

        // 打印
        System.out.println(result);

        MyBatisUtils.commitAndclose();
    }

8.4.4 修改

@Test
    public void testUpdate() {
        UserMapper2 userMapper2 = MyBatisUtils.getMapper(UserMapper2.class);

        User user = new User();
        user.setUid("2");
        user.setUsername("jack");
        user.setPassword("1234");
        user.setName("杰克");
        user.setEmail("itcast_lt@163.com");
        user.setBirthday(new Date());
        user.setSex("男");
        user.setSex("0");

        int result = userMapper2.updateByPrimaryKey(user);

        // 打印
        System.out.println(result);

        MyBatisUtils.commitAndclose();
    }

8.4.5 删除

    @Test
    public void testDelete() {
        UserMapper2 userMapper2 = MyBatisUtils.getMapper(UserMapper2.class);

        int result = userMapper2.deleteByPrimaryKey("2");

        // 打印
        System.out.println(result);

        MyBatisUtils.commitAndclose();
    }

8.4.6 多条件查询

  • 语法:
// 获得多条件对象
Example example = new Example(对象.class);
Example.Criteria criteria = example.createCriteria();

// 常见条件方法
andLike()					//模糊查询
andEqualTo()				//等值查询
andLessThanOrEqualTo()		//<=查询
andGreaterThanOrEqualTo()	//>=查询
andBetween()				//区间查询
@Test
    public void testCondition() {
        UserMapper2 userMapper2 = MyBatisUtils.getMapper(UserMapper2.class);

        Example example = new Example(User.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andLike("name", "%王%");
        criteria.andEqualTo("sex", "男");

        List<User> list = userMapper2.selectByExample(example);
        for (User user : list) {
            System.out.println(user);
        }

        MyBatisUtils.commitAndclose();
    }

总结:学完之后还是会有疑问,通用mapper可以用多表查询吗,可以再去网上查一波。注解版目前是学完了,还有xml版,其实原理一样,只不过适用场景不同罢了。加油,离工作又进了一天。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值