Mybatis的使用

创建两个关联表,一个老师teacher表,一个student学生表,student有一个t_id关联teacher表的主键id,数据库如下图:

teacher表:

student表:

分层结构如下

DemoSqlMap.xml连接数据库的配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="mysql">
        <environment id="mysql">
            <!--配置事务的类型,使用本地事务策略-->
            <transactionManager type="JDBC"></transactionManager>
            <!--是否使用连接池 POOLED表示使用链接池,UNPOOLED表示不使用连接池-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/artic"/>
                <property name="username" value="root"/>
                <property name="password" value="123456789"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mapper/StudentDao.xml"></mapper>
        <mapper resource="mapper/TeacherDao.xml"></mapper>
    </mappers>
</configuration>

teacher实体类,含有get和set和tostring方法:

public class Teacher {
    private Integer id;
    private String tname;
    //一个老师对应多个学生,查询时用List来接收
    private List<Student> students;
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getTname() {
        return tname;
    }

    public void setTname(String tname) {
        this.tname = tname;
    }

    public List<Student> getStudents() {
        return students;
    }

    public void setStudents(List<Student> students) {
        this.students = students;
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "id=" + id +
                ", tname='" + tname + '\'' +
                ", students=" + students +
                '}';
    }
}

 student实体类:

public class Student {
    private Integer id;
    private String sname;
    private String sex;
    private Integer age;
    private Integer t_id;
    //一个学生对应一个教师,用Teacher来接收而不是List
    private Teacher teacher;


    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getT_id() {
        return t_id;
    }

    public void setT_id(Integer t_id) {
        this.t_id = t_id;
    }

    public Teacher getTeacher() {
        return teacher;
    }

    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", sname='" + sname + '\'' +
                ", sex='" + sex + '\'' +
                ", age=" + age +
                ", t_id=" + t_id +
                ", teacher=" + teacher +
                '}';
    }
}

mybatis有两种常用的联表查询方法:

第一种: 连表查询

使用的联表查询语句

教师因为有多个学生,所以需要用List来接收这个教师所对应的的学生

查询全部教师的和每个教师对应的全部学生的dao层方法如下:

 List<Teacher> getTeacher();

 这个方法对应的xml中的sql语句如下:

    <select id="getTeacher" resultMap="Map">
        SELECT  * FROM teacher LEFT JOIN student  on student.t_id = teacher.id
    </select>
    <resultMap id="Map" type="com.qcby.entity.Teacher">
        <result property="id" column="id"/>
        <result property="tname" column="tname"/>
        <!-- 复杂的属性我么需要单独去处理 对象:association   集合:collection
          在集合中的泛型信息,我们使用ofType获取
          -->
        <collection property="students" ofType="com.qcby.entity.Student">
            <result property="sname" column="sname"/>
        </collection>
    </resultMap>

里面select标签对应的就是查询方法,在里面写查询方法,这种方法是通过连表查询语句来获取数据的.

resultType可以指定pojo将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。

如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,resultMap实质上还需要将查询结果映射到pojo对象中。 resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。

这里需要使用resultMapresultMap标签中的id属性和select标签中的resultMap属性相对应,type属性是映射到哪个实体类。

resultMap标签中的result 标签的property属性对应的是java实体类中的字段名,column属性对应的是数据库中的字段名。

collection 标签是对一对多查询时,一个教师对应的多个学生,学生是个集合,所以需要用collection 标签来接收多个学生

我们在测试类中对它进行测试,输出结果如下:

而如果是学生进行查询,一个学生对应的是一个教师就不能使用 collection 标签而是使用association   标签,

学生的dao层方法:

    List<Student> getStudent();

查询的mapper配置文件 如下:

 <select id="getStudent" resultMap="Map">
        SELECT  * FROM student
        LEFT JOIN teacher  on student.t_id = teacher.id
    </select>
    <resultMap id="Map" type="com.qcby.entity.Student">
        <id property="id" column="id"/>
        <result property="sname" column="sname"/>
        <result property="sex" column="sex"/>
        <result property="age" column="age"/>
        <result property="t_id" column="t_id"/>
        <association property="teacher" javaType="com.qcby.entity.Teacher">
            <id property="id" column="t_id"/>
            <result property="tname" column="tname"/>
        </association>
    </resultMap>

这里学生和教师不同的就是学生使用的是association   标签它对应的是一个实体。

测试类查询结果如下:

 第二种方法 分步查询:

和第一种方法不同,第一种方法是直接通过连表查询语句把数据直接查询出来,第二种是把查询语句分成两步。

用教师来举例,会先把教师查出来,再通过教师id来找到对应的全部学生,这是使用的两个sql语句。

teacher的xml查询如下:


    <select id="getTeacher" resultMap="Map">
        select * from teacher
    </select>
    <resultMap id="Map" type="com.qcby.entity.Teacher">
      <id property="id" column="id"/>
        <result property="tname" column="tname"/>
        <collection javaType="ArrayList" ofType="com.qcby.entity.Student"                             
            select="getStudent" property="students" column="id"/>
    </resultMap>
    <select id="getStudent" resultType="com.qcby.entity.Student">
        select * from student where t_id=#{id}
    </select>

collection 标签里的select属性是这个集合会对应哪个查询的id会把查询的数据放入这个集合内, column属性作用就是会传给这个查询语句什么参数,这个参数来自上一个查询语句的某个数据库字段。总体意思就是会先查全部教师,再查学生,而学生里面对应的id是通过column获取的。

学生查询的第二种方式的xml如下,

 <select id="getStudent" resultMap="Map">
        select * from student
    </select>
    <resultMap id="Map" type="com.qcby.entity.Student">
        <id property="id" column="id"/>
        <result property="sname" column="sname"/>
        <result property="sex" column="sex"/>
        <result property="age" column="age"/>

        <association property="teacher" column="t_id" select="getTeacher"/>
    </resultMap>
    <select id="getTeacher" resultType="com.qcby.entity.Teacher">
        select * from teacher where id=#{id}
    </select>

查询结果和第一种的查询结果一致,只是查询方式不同,这种方法采用了分布查询,使用哪种方式都可以。

#{}和${}

在查询时where语句后会有#{},括号里放的就是我们传来的参数。

${}和#{}作用相同,${}的本质是字符串拼接,#{}的本质是占位符赋值

${}使用字符串拼接的方式拼接sql,若为字符串类型或日期类型的字段进行赋值时,需要手动加单引号;

#{}使用占位符赋值的方式拼接sql,此时为字符串类型或日期类型的字段赋值时,可以自动添加单引号;

使用#{}这种方式最好它比较安全,而${}容易出现sql注入的问题,不建议使用。

mybatis的增删改:

在xml文件中的添加语句

<!--返回主键 :我们的主键需要设置自动递增 -->

<insert id="insertGetId" parameterType="com.qcby.entity.User">

    <selectKey keyProperty="id" resultType="int" order="AFTER">

        SELECT LAST_INSERT_ID()

    </selectKey>

            insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})

</insert>

 parameterType属性是传入的参数来自哪个类或属于哪种数据类型。

<selectKey keyProperty="id" resultType="int" order="AFTER">

        SELECT LAST_INSERT_ID()

</selectKey>

它的作用就是返回主键 ,就是添加数据后会把新添加的数据的主键id返回给这个实体类,不加它就没有返回主键这个功能。

更新语句如下:

<update id="update" parameterType="com.qcby.entity.User">

        update user set username = #{username},birthday = #{birthday}, sex = #{sex},address = #{address} where id = #{id}

</update>

删除语句如下:

 <delete id="delete" parameterType="java.lang.Integer">

        delete from user where id = #{id}

</delete>

动态sql

什么是动态sql:在不同条件下拼接不同的sql

Mybatis框架的动态sql技术是一种根据特定条件动态拼接SQl语句的功能,他存在的意义是为了解决拼接SQL语句字符串时的痛点问题。其中一些条件可以选择也可以不选择,那么如果使用传统的方式进行查询,反而在拼接sql的时候会造成一些列的问题。

<if>标签

看如下sql:

<select id="selectUserByUsernameAndSex" parameterType="com.qcby.entity.User"
        resultType="com.qcby.entity.User">
    select * from user where username = #{username} and sex = #{sex}
</select>

 如果查询时username或sex为空,那么我们就不让username或sex出现在查询语句上,那么我们就需要使用<if>标签,写法如下:

<select id="selectUserByUsernameAndSex" parameterType="com.qcby.entity.User"
        resultType="com.qcby.entity.User">
    select * from user where
    <if test="username != null and username = ''">
        username=#{username}
    </if>
    <if test="sex != null and sex !=''">
       and sex=#{sex}
    </if>
</select>

 那如果username为空时,sex前面就会多一个and,sql语句就会不正确。

<where>标签

上面导致的错误如何解决,使用where标签,会帮我们把where后第一个and或者or去除掉,代码如下。

<select id="selectUserByUsernameAndSex" parameterType="com.qcby.entity.User"
        resultType="com.qcby.entity.User">
    select * from user 
    <where>
        <if test="username != null and username = ''">
            username=#{username}
        </if>
        <if test="sex != null and sex !=''">
           and sex=#{sex}
        </if>
    </where>
</select>

<set>标签 

set标签 用在update更新语句,和if标签组装使用,代码如下:

<update id="update" parameterType="com.qcby.entity.User">
    update user
    <set>
        <if test="username !=null and username!=''">
            username = #{username} ,
        </if>
        <if test="address != null and address != ''">
             address = #{address}
        </if>
     </set>
     where id = #{id}
</update>

set可以去除掉无用的逗号,假如address为空,username不为空,就会导致username那一行多个逗号,导致语句错误,而这里使用了set标签,就不会产生错误。

<choose>、<when>和<otherwise>标签

这个标签相当于是我们java当中的if.....elseif.....else

<choose>标签是<when>标签和<otherwise>标签父标签,都在<choose>标签内部。

<when>标签就相当于是我们的 if 和 elseif

<otherwise>标签相当于是我们的 else

代码案例如下:

<select id="selectUserByChoose" resultType="com.qcby.entity.User"
        parameterType="com.qcby.entity.User">
    select * from user
    <where>
        <choose>
            <when test="id !='' and id != null">
                id=#{id}
            </when>
            <when test="username !='' and username != null">
                and username=#{username}
            </when>
            <otherwise>
                and sex=#{sex}
            </otherwise>
        </choose>
    </where>
</select>

其实和<if>标签作用一样。

<trim>标签 

trim标记是一个格式化的标记,可以完成set或者是where标记的功能

trim里面有两个属性:

1.prefix:前缀,里面写where代表是where标签,写set代表set标签     

2.prefixoverride:去掉第一个and或者是or还或者是逗号,写什么可以去除哪一项

trim充当where代码如下:

<select id="selectUserByUsernameAndSex" parameterType="com.qcby.entity.User"
            resultType="com.qcby.entity.User">

        select * from user
        <trim prefix="where" prefixOverrides="and | or">
            <if test="username != null">
                and username=#{username}
            </if>
            <if test="sex != null">
                and sex=#{sex}
            </if>
        </trim>
    </select>

 trim充当set代码如下:

 <update id="update" parameterType="com.qcby.entity.User">
        update user
        <trim prefix="set" suffixOverrides=",">
            <if test="username != null and username != ''">
                username = #{username},
            </if>
            <if test="sex != null and sex != ''">
                sex = #{sex},
            </if>
        </trim>
        where id = #{id}
 </update>

<foreach>标签 

我们进行批量删除和批量添加的时候,数据是数组或是list集合,就需要使用foreach标签来进行批量插入和批量删除。

foreach中有如下几种属性:

1. collection:当前要循环的数组或者集合 

2. item: 我们指定要循环的数组的每一个元素

3. separator:每一个元素应该用什么来做分割 

4. open:当前循环是以什么开始 

5. close:当前循环是以什么结束 

批量删除案例如下:

mapper层:

/**
 * 通过数组批量删除
 * @param ids
 * @return
 */
int deleteMoreByArray(@Param("ids") Integer[] ids);
<!-- 批量删除的sql语句:delete from user where id in (1,2,3,4,5);   -->
<delete id="deleteMoreByArray">
    delete from user where id in
        <foreach collection="ids" item="id" separator="," open="(" close=")">
            #{id}
        </foreach>
</delete>

批量插入案例:

/**
 * 通过集合批量添加
 * @param users
 * @return
 */
int insertMoreByList(@Param("users") List<User> users);

xml:

<insert id="insertMoreByList" >
    insert into user(id,username,birthday,sex,address) values
    <foreach collection="users" item="user" separator=",">
        (null,#{user.username},#{user.birthday},#{user.sex},#{user.address})
    </foreach>
</insert>

java中的foreach循环如下:

for ( User user : users) {}

 collection属性中的users代表迭代对象,item代表迭代出的实例。

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sshm_666

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值