Mybatis中的传参以及增删改查

Mybatis中的传参以及增删改查

参数传递

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

单个参数直接传递

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

注意: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();
}

传递多个参数

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

如:

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

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

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

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

 <typeAliases>
        <package name="com.ffyc.mybatis.modle"/>
    </typeAliases>

新增

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

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

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

在测试中执行完测试方法后数据库表的数据并没有变化,是因为我们使用的是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();
    }

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

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

 <!--
    useGeneratedKeys:true 开启返回数据库中自动生成的主键的
    keyColumn:主键列
    keyProperty:属性是什么
添加这三个属性后,会将keyColumn的值封装到keyProperty属性中
    -->
    <insert id="insert" parameterType="Student" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
        insert into student (name,gender) values (#{name},#{gender})
    </insert>
<!--
    注意:返回的主键并不是返回到方法的返回值,而是封装到student对象的id属性中
    -->

#{}和${}的区别

#{}占位符

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

${}拼接符

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

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

修改

  1. 在代理接口中添加方法;
int upDate(Student student);
  1. 在对应的Mapper.xml文件中添加SQL语句
  <update id="upDate" parameterType="Student">
        update student set name=#{name},gender=#{gender} where id = #{id}
    </update>
  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. 在代理接口中添加方法;
int Delete(int id);
  1. 在对应的Mapper.xml文件中添加SQL语句
  <delete id="Delete" parameterType="int">
        delete from student where id = #{id}
    </delete>
  1. 测试
 @Test
    public void test3(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        StudentDao studentDao = sqlSession.getMapper(StudentDao.class);

        studentDao.Delete(5);
        sqlSession.commit();
        sqlSession.close();
    }

查询

我们当时在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);
            }

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

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

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

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

	student_phone CHAR(11)

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

 private String studentPhone;

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

<!-- 从经典的数据库命名方式转为java的驼峰命名 user_ name==>userName -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
  1. 单张表中可以在SQL语句中定义别名,别名与属性名相同也可以封装到对象中。
select name,gender six,student_phone from student where id = #{id}
  1. 特殊情况,单独处理
<!--
    resultMap标签中 id:map标识   type:表示返回值的数据类型
    在resultMap标签里面我们需要做的是将列名和属性名对应上
    单张表时只需要用在名称不一样的列中,相同的会自动映射
    -->
    <resultMap id="findStudentMap" type="Student">
        <!--用来定义列名和属性名之间的关系:将gender列封装在six属性中-->
        <result column="gender" property="six"></result>
    </resultMap>
    <select id="findStudentById" resultMap="findStudentMap">
        select name,gender,student_phone from student where id = #{id}
    </select>

查询结果为多条结果时

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

 List<Student> findStudent();

多张表关联查询时

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

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

    private String gradeName;
    private int gradeid;

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

private Grade grade;

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

 <resultMap id="findStudentMap" type="student">
        <!--id :主键映射   result:其他字段映射 association 嵌套结果映射 -->
        <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>
        <!--javaType表示java中的类型是什么-->
         <association property="grade" javaType="Grade">
             <!--将gname 封装到Grade 的name属性中-->
             <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>

需要注意的是:

		<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>

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

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

<!--是否自动映射-->
<setting name="autoMappingBehavior" value="FULL"/>

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

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

如果想查询学生集合时:

List<Student> findStudentList();
<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>

由以上代码知,在查询集合和查询单条数据都可以用同一条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>

一对多查询

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

//年级实现类
public class Grade {
    private Integer id;
    private String name;
    private Set<Student> students = new HashSet<>();
}

对应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>

嵌套查询

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

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

 <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). 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);

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

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

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

@Param : 入参

@Results : 设置结果集合

@Result : 结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值