17-mybatis进阶

接口代理方式实现Dao(重要)

1 接口代理的要求【记住】

1、映射配置文件中的名称空间要和接口的全类名相同
2、映射配置文件中标签的id属性值要和接口的方法名相同     形象比喻为namespace+id=接口全类名+方法名
3、映射配置文件中标签的parameterType属性值要和方法的参数类型一致
4、映射配置文件中标签的resultType属性值要和方法的返回值类型一致

在这里插入图片描述

2 代码演示

第一步:准备接口
package com.itheima.mapper;

/*
    持久层接口
 */
public interface StudentMapper {
    //查询全部
    public abstract List<Student> selectAll();
    //根据id查询
    public abstract Student selectById(Integer id);
    //新增数据
    public abstract Integer insert(Student stu);
    //修改数据
    public abstract Integer update(Student stu);
    //删除数据
    public abstract Integer delete(Integer id);
    //多条件查询
    public abstract List<Student> selectCondition(Student stu);
    //根据多个id查询
    public abstract List<Student> selectByIds(List<Integer> ids);
}
第二步:编写/修改映射文件
<!--namespace="com.itheima.mapper.StudentMapper" :接口的全类名-->

<mapper namespace="com.itheima.mapper.StudentMapper">
  
  
  <!--id必须是接口的方法名-->
  <!--查询所有学生信息-->
  <select id="selectAll" resultType="student">
    select * from student
  </select>

  <!--根据id查询学生信息-->
  <select id="selectById" parameterType="int" resultType="student">
    select * from student where id=#{ID}
  </select>

  <!--添加学生-->
  <insert id="insert" parameterType="student">
    insert into student values(null,#{name},#{age})
  </insert>

  <!--修改学生信息-->
  <update id="update" parameterType="student">
    update student set name=#{name},age=#{age} where id=#{id}
  </update>

  <!--删除学生信息-->
  <delete id="delete" parameterType="int">
    delete from student where id=#{id}
  </delete>
</mapper>
第三步:编程测试类测试
public class StudentTest {

  @Test
  public void testSelectAll() throws IOException {
    //1、加载核心配置文件
    InputStream is = Resources.getResourceAsStream("MybatisConfig.xml");
    //2、获取工厂对象
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
    //3、获取SqlSession核心对象
    SqlSession sqlSession = factory.openSession(true);
    
    //4、获取接口的实现类代理对象,执行操作
    //返回了一个代理对象, 这个 代理对象 是通过 jdk的 动态代理来实现的 
    // Proxy.newInstance();
    
    StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
    
    
    List<Student> list = mapper.selectAll();
    
    
    //5、处理/打印结果
    list.forEach(stu-> System.out.println(stu));
    //6、释放资源
    sqlSession.close();
  }


  @Test
  public void testSelectById() throws IOException {
    //1、加载核心配置文件
    InputStream is = Resources.getResourceAsStream("MybatisConfig.xml");
    //2、获取工厂对象
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
    //3、获取SqlSession核心对象
    SqlSession sqlSession = factory.openSession(true);
    
    //4、获取接口的实现类代理对象,执行操作
    StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
    Student student = mapper.selectById(3);
    //5、处理/打印结果
    System.out.println(student);
    //6、释放资源
    sqlSession.close();
  }

  @Test
  public void testSelectDelete() throws IOException {
    //1、加载核心配置文件
    InputStream is = Resources.getResourceAsStream("MybatisConfig.xml");
    //2、获取工厂对象
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
    //3、获取SqlSession核心对象
    SqlSession sqlSession = factory.openSession(true);
    //4、获取接口的实现类代理对象,执行操作
    StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
    Integer count = mapper.delete(8);
    //5、处理/打印结果
    System.out.println("count = " + count);//返回影响的行数
    //6、释放资源
    sqlSession.close();
  }
}

3.@Param注解

给参数取名字
public abstract List<Student> selectByNameOrAge(@Param("p1")String name,@Param("p2")Integer age)
    
<select id="selectByNameOrAge">
  select * from student name=#{p1} or age=#{p2}
</select>

动态SQL(理解)

1.if 标签判断(重要)

第一步:配置SQL
<!--多条件查询-->
<select id="selectCondition" resultType="student" parameterType="student">
  select * from student
  <where>
    <!--test="" 是判断条件-->
    <if test="id != null">
      id=#{id}
    </if>
    <if test="name != null and name !='' ">
      and name=#{name}
    </if>
    <if test="age != null">
      and age=#{age}
    </if>
  </where>
</select>
第二步:测试
@Test
public void testSelectCondition() throws IOException {
  //1、加载核心配置文件
  InputStream is = Resources.getResourceAsStream("MybatisConfig.xml");
  //2、获取工厂对象
  SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
  //3、获取SqlSession核心对象
  SqlSession sqlSession = factory.openSession(true);
  //4、获取接口的实现类代理对象,执行操作
  StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
  //创建条件
  Student stu=new Student();
  //stu.setId(2);
  stu.setAge(25);
  //执行查询
  List<Student> list = mapper.selectCondition(stu);
  
  //5、处理/打印结果
  list.forEach(student -> System.out.println(student));
  //6、释放资源
  sqlSession.close();
}

2.foreach标签遍历(了解)

第一步:配置SQL
<!--多条件查询-->
<select id="selectByIds" resultType="student">
  select * from student
  <where>
    <!--
                collection="" 遍历数组写array,遍历集合写list,遍历map集合写map
                open="id in(" 以xxx开头
                close=")" 以xxx结尾
                item="" 遍历的每一个元素的名称,变量名随便写,写啥后面就用啥
                separator="," 分隔符
                index="" 如果遍历的是数组或者单列集合,就表示索引。如果遍历的是map就表示key
            -->
    <foreach collection="list" open="id in(" close=")" item="id" separator=",">
      <!--#{id} 大括号中的名称就是item的属性值-->
      #{id}
    </foreach>
  </where>
</select>

select * from student where id in(1,2,3,4)
第二步:测试
@Test
public void testSelectByIds() throws IOException {
  //1、加载核心配置文件
  InputStream is = Resources.getResourceAsStream("MybatisConfig.xml");
  //2、获取工厂对象
  SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
  //3、获取SqlSession核心对象
  SqlSession sqlSession = factory.openSession(true);
  //4、获取接口的实现类代理对象,执行操作
  StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
	
  //创建条件
  List<Integer> ids = List.of(1, 2,3);
  //执行查询
  List<Student> list = mapper.selectByIds(ids);
  //5、处理/打印结果
  list.forEach(student -> System.out.println(student));
  //6、释放资源
  sqlSession.close();
}

批量插入,批量删除

<!--批量删除-->
<delete id="deleteMany" parameterType="int[]">
        delete from student where id  in
        <foreach collection="array" item="id" open="(" close=")" separator=",">
              #{id}
        </foreach>
</delete>
<!--批量插入-->
<insert id="insertMany" parameterType="list">
        insert into student values
        <foreach collection="list" item="list" separator=",">
            (#{list.id},#{list.name},#{list.age})
        </foreach>
</insert>

3.SQL片段抽取

- 我们可以将一些重复性的sql语句进行抽取,以达到复用的效果
- <sql>:抽取SQL语句标签
    <sql id="片段的唯一标识">抽取的SQL语句</sql>
- <include>:引入SQL片段标签
    <include refid="片段唯一标识"/>

分页插件(重要)

1、导入jar包
2、在核心配置文件中配置分页插件
  <!--集成PageHelper分页插件-->
  <plugins>
    <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
  </plugins>

3、在查询所有之前设置开始页和每页条数:PageHelper.startPage(页码,每页条数)

4、查询之后使用PageInfo封装分页数据: PageInfo<> info=new PageInfo(list);

1.导入开发jar包

jsqlparser-3.1.jarpagehelper-5.1.10.jar , 记得要 add as library

2.在mybatis的核心配置文件中集成分页插件

<!--集成PageHelper分页插件-->
<plugins>
  <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>

3.在查询所有信息之前设置查询的页数和每页展示条数

@Test
public void testSelectAll() throws IOException {
  //1、加载核心配置文件
  InputStream is = Resources.getResourceAsStream("MybatisConfig.xml");
  //2、获取工厂对象
  SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
  //3、获取SqlSession核心对象
  SqlSession sqlSession = factory.openSession(true);
  //4、获取接口的实现类代理对象,执行操作
  StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

  //使用分页助手设置页数和每页条数
  PageHelper.startPage(1,3); //------------------------------

  List<Student> list = mapper.selectAll();
    
  //5、处理/打印结果
  list.forEach(stu-> System.out.println(stu));
  //6、释放资源
  sqlSession.close();
}

4.在获取分页数据之后封装分页信息

@Test
public void testSelectAll() throws IOException {
  //1、加载核心配置文件
  InputStream is = Resources.getResourceAsStream("MybatisConfig.xml");
  //2、获取工厂对象
  SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
  //3、获取SqlSession核心对象
  SqlSession sqlSession = factory.openSession(true);
  //4、获取接口的实现类代理对象,执行操作
  StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

  //使用分页助手设置页数和每页条数
  //参数1:当前页码,参数2:每页显示条数
  PageHelper.startPage(1,3); //------------------------------

  List<Student> list = mapper.selectAll();

  //封装分页信息
  PageInfo<Student> info=new PageInfo<>(list);//---------------------------
  
  
  //打印分页信息
  System.out.println("当前页数:"+info.getPageNum());  //1
  System.out.println("每页展示条数:"+info.getPageSize()); //3
  System.out.println("总页数:"+info.getPages());
  System.out.println("总条数:"+info.getTotal());
  System.out.println("当前页条数:"+info.getSize());
  System.out.println("上一页:"+info.getPrePage());
  System.out.println("下一页:"+info.getNextPage());
  System.out.println("是否是第一页:"+info.isIsFirstPage());
  System.out.println("是否是最后一页:"+info.isIsLastPage());

  //5、处理/打印结果
  list.forEach(stu-> System.out.println(stu));
  //6、释放资源
  sqlSession.close();
}

mybatis多表操作(重要)

数据库准备

CREATE DATABASE db2;

USE db2;

-- 一对一
CREATE TABLE person(
  id INT PRIMARY KEY AUTO_INCREMENT,
  NAME VARCHAR(20),
  age INT
);

INSERT INTO person VALUES (NULL,'张三',23);
INSERT INTO person VALUES (NULL,'李四',24);
INSERT INTO person VALUES (NULL,'王五',25);

CREATE TABLE card(
  id INT PRIMARY KEY AUTO_INCREMENT,
  number VARCHAR(30),
  pid INT,
  CONSTRAINT cp_fk FOREIGN KEY (pid) REFERENCES person(id)
);

INSERT INTO card VALUES (NULL,'12345',1);
INSERT INTO card VALUES (NULL,'23456',2);
INSERT INTO card VALUES (NULL,'34567',3);


-- 一对多
CREATE TABLE classes( -- 班级表
  id INT PRIMARY KEY AUTO_INCREMENT,
  NAME VARCHAR(20)
);
INSERT INTO classes VALUES (NULL,'黑马一班');
INSERT INTO classes VALUES (NULL,'黑马二班');


CREATE TABLE student( -- 学生表
  id INT PRIMARY KEY AUTO_INCREMENT,
  NAME VARCHAR(30),
  age INT,
  cid INT,
  CONSTRAINT cs_fk FOREIGN KEY (cid) REFERENCES classes(id)
);
INSERT INTO student VALUES (NULL,'张三',23,1);
INSERT INTO student VALUES (NULL,'李四',24,1);
INSERT INTO student VALUES (NULL,'王五',25,2);
INSERT INTO student VALUES (NULL,'赵六',26,2);

-- 多对多
CREATE TABLE course(-- 课程
  id INT PRIMARY KEY AUTO_INCREMENT,
  NAME VARCHAR(20)
);
INSERT INTO course VALUES (NULL,'语文');
INSERT INTO course VALUES (NULL,'数学');


CREATE TABLE stu_cr(
  id INT PRIMARY KEY AUTO_INCREMENT,
  sid INT,
  cid INT,
  CONSTRAINT sc_fk1 FOREIGN KEY (sid) REFERENCES student(id),
  CONSTRAINT sc_fk2 FOREIGN KEY (cid) REFERENCES course(id)
);
INSERT INTO stu_cr VALUES (NULL,1,1);
INSERT INTO stu_cr VALUES (NULL,1,2);
INSERT INTO stu_cr VALUES (NULL,2,1);
INSERT INTO stu_cr VALUES (NULL,2,2);

一对一关系

1 javabean类
public class Card {
    private Integer id;     //主键id
    private String number;  //身份证号
  
    private Person p;       //所属人的对象
  
}
public class Person {
    private Integer id;     //主键id
    private String name;    //人的姓名
    private Integer age;    //人的年龄
}
2 接口类
public interface OneToOneMapper {
    //查询全部
    public abstract List<Card> selectAll();
}
3 映射文件配置OneToOneMapper.xml

resultMap标签的作用:手动定义查询结果和bean对象的映射关系,一般用来处理查询结果和bean的属性不一致情况。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.itheima.mapper.OneToOneMapper">
  <!--配置查询结果和bean对象的对应关系-->
  <resultMap id="oneToOne" type="card">
    <!--封装主键信息,column="id"列名称,property="id"bean中的属性名称-->
    <id column="id" property="id"/>
    <!--封装非主键信息-->
    <result column="number" property="number"/>
    <!--配置包含的对象映射关系,配置一对一关系,javaType="person"表示bean的属性类型-->
    
    <association property="p" javaType="person">
      <!--封装主键信息-->
      <id column="pid" property="id"/>
      <!--封装非主键信息-->
      <result column="name" property="name"/>
      <result column="age" property="age"/>
    </association>
    
  </resultMap>

  <!-- 测试一对一关系:查询所有card的信息,包括每个card对应的person信息-->
  <select id="selectAll" resultMap="oneToOne">
    select c.*,p.NAME,p.age from card c ,person p where c.pid=p.id;
  </select>
  
</mapper>

注意:封装结果集不再使用resultType属性,而是使用resultMap属性。

4 测试类
/*
        测试一对一关系:查询所有card的信息,包括每个card对应的person信息
     */
@Test
public void testOneToOneMapper(){
  //加载资源
  SqlSession sqlSession = null;
  try {
    InputStream is = Resources.getResourceAsStream("MybatisConfig.xml");
    //获取SqlSessionFactory对象
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
    //获取SqlSession对象
    sqlSession = factory.openSession(true);
    //获取mapper接口的代理对象,执行方法
    OneToOneMapper mapper = sqlSession.getMapper(OneToOneMapper.class);
    List<Card> cards = mapper.selectAll();
    //打印结果
    cards.forEach(card -> System.out.println(card));
  } catch (IOException e) {
    e.printStackTrace();
  } finally {
    //释放资源
    sqlSession.close();
  }
}

一对多关系 (重要)

1 javabean类
public class Classes {
  private Integer id;     //主键id
  private String name;    //班级名称

  private List<Student> students; //班级中所有学生对象,一个班级中有多名学生
  
  // 生成 get/set 方法 
}

public class Student {
    private Integer id;     //主键id
    private String name;    //学生姓名
    private Integer age;    //学生年龄
  
    // 生成 get/set 方法 
}
2 接口类
public interface OneToManyMapper {
  //查询全部
  public abstract List<Classes> selectAll();
}
3 映射文件配置
<resultMap id="OneToMany" type="classes">
        <id column="cid" property="id"/>
        <result column="cname" property="name"/>
        <!--
            collection:配置被包含的集合对象映射关系
            property:被包含对象变量名
            ofType:被包含对象的实际数据类型
        -->
        <collection property="students" ofType="student">
            <id column="sid" property="id"/>
            <result column="sname" property="name"/>
            <result column="sage" property="age"/>
        </collection>
    </resultMap>

    <select id="selectAll" resultMap="OneToMany">
        select c.id cid,c.NAME cname,s.id sid,s.NAME sname,s.age sage from classes c,student s where c.id=s.cid
    </select>
4 测试类
/*
        测试一对多关系:查询所有班级以及该班级的所有学生信息
     */
@Test
public void testOneToManyMapper(){
  //加载资源
  SqlSession sqlSession = null;
  try {
    InputStream is = Resources.getResourceAsStream("MybatisConfig.xml");
    //获取SqlSessionFactory对象
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
    //获取SqlSession对象
    sqlSession = factory.openSession(true);
    //获取mapper接口的代理对象,执行方法
    OneToManyMapper mapper = sqlSession.getMapper(OneToManyMapper.class);
    List<Classes> classes = mapper.selectAll();
    //打印结果
    classes.forEach(cla -> System.out.println(cla));
  } catch (IOException e) {
    e.printStackTrace();
  } finally {
    if(sqlSession!=null){
      //释放资源
      sqlSession.close();
    }
  }
}

多对多关系重要

1 javabean类
public class Student {
    private Integer id;     //主键id
    private String name;    //学生姓名
    private Integer age;    //学生年龄
    private List<Course> courses;   // 学生所选择的课程集合
}
public class Course {
    private Integer id;     //主键id
    private String name;    //课程名称
}
2 接口类
public interface ManyToManyMapper {
  //查询全部
  public abstract List<Student> selectAll();
}
3 映射文件配置
<resultMap id="manyToMany" type="student">
  <id column="sid" property="id"/>
  <result column="sname" property="name"/>
  <result column="sage" property="age"/>

  <!--封装数据到集合中-->
  <collection property="courses" ofType="Course">
    <id column="cid" property="id"/>
    <result column="cname" property="name"/>
  </collection>
  
</resultMap>

<select id="selectAll"  resultMap="manyToMany">
  select s.id sid,s.NAME sname,s.age sage,c.id cid,c.NAME cname from student s,stu_cr sc,course c where s.id=sc.sid and c.id=sc.cid;
</select>
4 测试类
/*
        测试多对多关系:查询所有学生及其选课信息
     */
@Test
public void testManyToManyMapper(){
  //加载资源
  SqlSession sqlSession = null;
  try {
    InputStream is = Resources.getResourceAsStream("MybatisConfig.xml");
    //获取SqlSessionFactory对象
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
    //获取SqlSession对象
    sqlSession = factory.openSession(true);
    //获取mapper接口的代理对象,执行方法
    ManyToManyMapper mapper = sqlSession.getMapper(ManyToManyMapper.class);
    List<Student> list = mapper.selectAll();
    //打印结果
    list.forEach(stu -> System.out.println(stu));
  } catch (IOException e) {
    e.printStackTrace();
  } finally {
    if(sqlSession!=null){
      //释放资源
      sqlSession.close();
    }
  }
}

注意:javaType属性和ofType属性的区别?

javaType的值用来表示bean对象的属性类型,ofType的值用来表示集合中元素的类型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值