• Mybatis中的传参以及增删改查


    Mybatis中的传参以及增删改查

    参数传递

    参数传递分为单个参数、多个参数。

    单个参数直接传递

    1. 需要在代理接口中声明一个方法
    Student findStudent(int id);
    
    • 1
    1. 在对应的studentMapper.xml中:
    <select id="findStudent" parameterType="int" resultType="com.ffyc.mybatis.modle.Student">
            select name,gender from student where id = #{id}
        select>
    
    • 1
    • 2
    • 3

    注意:select中的id应当与代理接口中的方法名相同,parameterType表示传过来的参数的类型,resultType表示返回值的类型。

    1. 测试:
    public void test(){
            SqlSession sqlSession = MybatisUtil.getSqlSession();
            StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
            Student student = studentDao.findStudent(1);
            System.out.println(student);
            sqlSession.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    传递多个参数

    传递多个参数时需要在代理接口中使用@Param(“id”)绑定,其他步骤不变。

    如:

    Student selectStudent(@Param("name") String name  , @Param("id") int id);
    
    • 1

    如果参数过多,并且具有一定的规范,可以传递一个对象,此时就需要使用parameterType参数进行定义类型,如:

    //代理接口中
    void insert(Student student);
    
    • 1
    • 2
     <insert id="insert" parameterType="Student">
            insert into student (name,gender) values (#{name},#{gender})
        insert>
    
    • 1
    • 2
    • 3

    注意:parameterType属性可以直接写Student是因为在mybatisConfig.xml中使用了别名配置:

     <typeAliases>
            <package name="com.ffyc.mybatis.modle"/>
        typeAliases>
    
    • 1
    • 2
    • 3

    新增

    在上面的案例中已经有新增的例子了

    新增时如果只将代理对象中的方法声明为int类型的返回值时返回的是执行此操作改变的行数。

    //代理接口中
    int insert(Student student);
    
    • 1
    • 2

    在测试中执行完测试方法后数据库表的数据并没有变化,是因为我们使用的是JDBC的事物管理,在所打印的日志“Setting autocommit to false on JDBC Connection”可以看出,Mybatis中的JDBC自动提交管理是false关闭的 ,需要我们手动提交。

    public void test(){
            SqlSession sqlSession = MybatisUtil.getSqlSession();
            StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
            Student student = new Student();
            student.setGender("男");
            student.setName("大黑");
            studentDao.insert(student);
            sqlSession.commit();//提交数据库事务管理,告诉mysql所有的逻辑已经执行完了,你可以将所有sql语句执行了
            sqlSession.close();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    注意:只有在增删改查中需要手动提交事务管理。

    当有需求是:须知道插入数据的id时(id为自增的)只需要在Mapper.xml文件的对应添加标签中声明几个属性就好

     
        <insert id="insert" parameterType="Student" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
            insert into student (name,gender) values (#{name},#{gender})
        insert>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    #{}和${}的区别

    #{}占位符

    是经过预编译的编译好的SQL语句在取值,底层使用的是PreparedStatement对象,是安全的数据库访问#{}的方式可以有效地防止SQL注入。一般传值时使用。

    ${}拼接符

    会传入参数字符串,取值后再去编译SQL语句,${}的方式无法防止SQL注入。一般用来动态传递列名。

    Mybatis排序时使用order by 动态传参时用的是$ 而不是 #。

    修改

    1. 在代理接口中添加方法;
    int upDate(Student student);
    
    • 1
    1. 在对应的Mapper.xml文件中添加SQL语句
      <update id="upDate" parameterType="Student">
            update student set name=#{name},gender=#{gender} where id = #{id}
        update>
    
    • 1
    • 2
    • 3
    1. 测试
    @Test
        public void test2(){
            SqlSession sqlSession = MybatisUtil.getSqlSession();
            StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
            Student student = new Student(5,"leukemia","女");
            studentDao.upDate(student);
            sqlSession.commit();
            sqlSession.close();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    删除

    与之前一样

    1. 在代理接口中添加方法;
    int Delete(int id);
    
    • 1
    1. 在对应的Mapper.xml文件中添加SQL语句
      <delete id="Delete" parameterType="int">
            delete from student where id = #{id}
        delete>
    
    • 1
    • 2
    • 3
    1. 测试
     @Test
        public void test3(){
            SqlSession sqlSession = MybatisUtil.getSqlSession();
            StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
    
            studentDao.Delete(5);
            sqlSession.commit();
            sqlSession.close();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    查询

    我们当时在jdbc中查询到结果时需要循环,一个个手动的封装到对应属性当中

    如:

    while (resultSet.next()) {
                    Students student = new Students();
                    student.setId(resultSet.getInt("id"));
                    student.setNum(resultSet.getString("num"));
                    student.setName(resultSet.getString("name"));
                    student.setGender(resultSet.getString("gender"));
                    student.setPhone(resultSet.getString("phone"));
                    student.setGradeName(resultSet.getString("grade"));
                    student.setAdminName(resultSet.getString("account"));
                    student.setOpertime(resultSet.getTimestamp("oper_time"));
                    list.add(student);
                }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    使用Mybatis时就不需要在手动封装。

    查询结果为一条数据时,可以实现将记录自动封装到对象中,实现方法有:

    1. 表中的列名与对象属性名完全一致;
    2. 开启mapUnderscoreToCamelCase 实现列名与方法名之间的转换。

    当数据库表中列名含有下划线时,如:

    	student_phone CHAR(11)
    
    • 1

    可以在对应的实体类将属性严格按照驼峰命名

     private String studentPhone;
    
    • 1

    并且在mybatisConfig.xml配置文件中进行一个setting全局配置

    
    <setting name="mapUnderscoreToCamelCase" value="true"/>
    
    • 1
    • 2
    1. 单张表中可以在SQL语句中定义别名,别名与属性名相同也可以封装到对象中。
    select name,gender six,student_phone from student where id = #{id}
    
    • 1
    1. 特殊情况,单独处理
    
        <resultMap id="findStudentMap" type="Student">
            
            <result column="gender" property="six">result>
        resultMap>
        <select id="findStudentById" resultMap="findStudentMap">
            select name,gender,student_phone from student where id = #{id}
        select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    查询结果为多条结果时

    查询结果为多条数据时,非常简单,只需要将代理接口中的方法的返回值类型改为list集合就行

     List<Student> findStudent();
    
    • 1

    多张表关联查询时

    之前在jdbc中我们使用的是直接列所表示的意思当做一个私有属性,如:

    在创建学生对象时,学生表中会有年级id,对应到具体的某一个年级,在jdbc中是创建私有属性

        private String gradeName;
        private int gradeid;
    
    • 1
    • 2

    在Mybatis中只需要创建一个年级的私有属性就好

    private Grade grade;
    
    • 1

    在对应的Mapper.xml文件中的写法如下:

     <resultMap id="findStudentMap" type="student">
            
            <id column="id" property="id">id>
            <result column="gender" property="gender">result>
            <result column="name" property="name">result>
            <result column="student_phone" property="studentPhone">result>
            
             <association property="grade" javaType="Grade">
                 
                 <result column="gname" property="name">result>
             association>
        resultMap>
        <select id="findStudentById" resultMap="findStudentMap">
            SELECT
              s.id,
              s.name,
              s.gender,
              s.student_phone,
              g.name gname
            FROM
              student s
              LEFT JOIN grade g
                ON s.gradeid = g.id
            WHERE s.id = #{id}
        select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    需要注意的是:

    		<result column="id" property="id">result>
            <result column="gender" property="gender">result>
            <result column="name" property="name">result>
            <result column="student_phone" property="studentPhone">result>
    
    • 1
    • 2
    • 3
    • 4

    按照之前所学习的内容,这些属性名与列名相匹配,可以不写,但是当有嵌套结果映射时,自动映射就停止了。

    也是可以修改的。在配置文件中myBatisConfig.xml中

    
    <setting name="autoMappingBehavior" value="FULL"/>
    
    • 1
    • 2

    FULL:开启时,就会完全自动映射。当然也会存在问题,只要名字相同就会映射,如:在没有起别名的情况下,没有查询年级的id,但是Mybatis会自动将学生的id封装进年级的id中。

    NONE:不自动映射;PARTIAL:(默认的)单张表自动映射,有嵌套关联时关闭自动映射;FULL:一直开启自动映射。

    如果想查询学生集合时:

    List<Student> findStudentList();
    
    • 1
    <select id="findStudentList" resultMap="findStudentMap">
            SELECT
              s.id,
              s.name,
              s.gender,
              s.student_phone,
              g.name gname
            FROM
              student s
              LEFT JOIN grade g
                ON s.gradeid = g.id
        select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    由以上代码知,在查询集合和查询单条数据都可以用同一条resultMap。

    查询集合和查询单条数据的SQL语句大体相同,可以将SQL抽取出来:

    <select id="findStudentList" resultMap="findStudentMap">
           <include refid="selectStudent">include>
    select>
    
        <sql id="selectStudent">
            SELECT
              s.id,
              s.name,
              s.gender,
              s.student_phone,
              g.name gname
            FROM
              student s
              LEFT JOIN grade g
                ON s.gradeid = g.id
        sql>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    一对多查询

    例如:一个年级有很多学生,现在需要查询出某个年级的所有学生。

    //年级实现类
    public class Grade {
        private Integer id;
        private String name;
        private Set<Student> students = new HashSet<>();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    对应Mapper.xml文件中:

    <resultMap id="findGradeStudentMap" type="Grade">
            <id column="gid" property="id"/>
            <result column="gname" property="name"/>
            <collection property="students" javaType="java.util.HashSet" ofType="Student">
                <id column="id" property="id"/>
                <result column="name" property="name"/>
                <result column="gender" property="gender"/>
            collection>
        resultMap>
    
        <select id="findGradeStudent" resultMap="findGradeStudentMap">
    
            SELECT
              s.id,
              s.name,
              s.gender,
              g.id gid,
              g.name gname
            FROM
              grade g
              LEFT JOIN student s
                ON s.gradeid = g.id
        select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    嵌套查询

    将一个多表关联查询拆分为多次查询,先查询主表数据,然后查询关联表数据。

    先查出年级,通过年级在查学生。

     <resultMap id="findGradeStudentMap2" type="Grade">
            <id column="id" property="id"/>
            <result column="name" property="name"/>
            <collection property="students" javaType="list" ofType="Student" select="findStudent" column="id">
                <id column="id" property="id"/>
                <result column="name" property="name"/>
                <result column="gender" property="gender"/>
            collection>
    resultMap>
    
        <select id="findStudent" resultType="Student">
            select id,name,gender from student where gradeid=#{id}
        select>
    
        <select id="findGradeStudent2" resultMap="findGradeStudentMap2">
            SELECT
              g.id ,
              g.name
            FROM
              grade g
    
        select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    (1). select:指定关联查询对象的 Mapper Statement ID 为 findStudent

    (2). column=“id”:关联查询时将 id列的值传入 findStudent,并将 findStudent查询的结果映射到 Grade的 students属性中

    (3).collection 和 association 都需要配置 select 和 column 属性,两者配置方法相同

    注解方式

    @Insert : 插入 sql , 和 xml insert sql 语法完全一样

    如:

     @Insert("insert into grade (name) value (#{name})")
        void insert(String name);
    
    • 1
    • 2

    @Select : 查询 sql, 和 xml select sql 语法完全一样

    @Update : 更新 sql, 和 xml update sql 语法完全一样

    @Delete : 删除 sql, 和 xml delete sql 语法完全一样

    @Param : 入参

    @Results : 设置结果集合

    @Result : 结果

  • 相关阅读:
    docker 容器内服务随容器自动启动
    torch.bmm功能解读
    消息中间件-RabbitMq相关概念及原理介绍【图文并茂】
    3.css的各种选择器
    前端面试必会 递归 深拷贝 手写
    TSUMU58CDT9-1显示器芯片方案
    ThingsBoard源码解析-规则引擎
    Python期末复习题:流程控制
    flume笔记(三):自定义-自定义interceptor/自定义source/自定义sink
    lammps提取和保存data文件中力场参数的技巧
  • 原文地址:https://blog.csdn.net/qq_55931044/article/details/126270898