MyBatis框架(二)

1.通过dao和映射文件的关联来完成操作---企业开发模式

我们之前使用SqlSession封装的一些方法可以完成crud操作,但是SqlSession封装的方法,传递的参数statement, 传递占位符的参数只能传递一个。而且它的方法名称都是固定。而真实在开发环境下不使用SqlSession封装的方法,而是习惯自己定义方法,自己调用自己的方法。

1.1 实现

(1)创建一个dao接口并定义自己需要的方法。

public interface UserDao {
    /**
     * 查询所有
     * @return
     */
    public List<User> findAll();
}

(2)创建映射文件

<?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">
<!--namespace:命名空间
       必须和dao相同
-->
<mapper namespace="com.ykq.dao.UserDao">
    <select id="findAll" resultType="com.ykq.entity.User">
        select * from tb_user
    </select>
</mapper>

注意: namespace必须和dao接口一样,而且标签的id必须和你接口的方法名一样。

(3)测试

@Test
    public void testFindAll() throws Exception{
        Reader resourceAsReader = Resources.getResourceAsReader("mybatis.xml");
        SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(resourceAsReader);
        SqlSession session=factory.openSession();
		//获取相应接口的代理对象
        UserDao userDao=session.getMapper(UserDao.class);
        List<User> list = userDao.findAll();
        System.out.println(list);
        session.commit();
        session.close();
    }

常见bug

 namespace和接口名不对应或xml文件没有注册到mybatis配置文件中。

 映射文件中的标签id和接口中方法名不对应

2.传递多个参数。

在dao接口中某些方法可能需要传递多个参数,譬如: 登录(username,password

需要在参数处使用@Param()为参数起名。

3.添加时如何返回递增的主键值。

需要返回添加数据库后的id值。

<!--添加用户
          useGeneratedKeys:设置使用生成的主键
          keyProperty: 赋值给哪个属性
    -->
    <insert id="addUser" parameterType="com.ykq.entity.User"
            useGeneratedKeys="true" keyProperty="userId">
          insert into tb_user values(null,#{username},#{realname})
    </insert>

4.解决列名和属性名不一致。

问题: 查询时返回一个null,或者某个列没有值

可以有两种解决办法:

第一种: 为查询的列起别名,而别名和属性名一致。

<!--根据id查询学生信息-->
    <select id="findOne" resultType="com.ykq.entity.Student">
        select stu_id id,stu_name name,stu_age age from tb_stu where stu_id=#{id}
    </select>

第二种: 使用resultMap完成列和属性之间的映射关系。


    <resultMap id="StuMapper" type="com.ykq.entity.Student">
         <!--主键的映射关系 column:列名 property:属性名-->
         <id column="stu_id" property="id"/>
         <!--普通列的映射关系-->
         <result column="stu_name" property="name"/>
         <result column="stu_age" property="age"/>
    </resultMap>

    <!--resultType和ResultMap二者只能用一个-->
    <select id="findOne" resultMap="StuMapper">
        select * from tb_stu where stu_id=#{id}
    </select>

若列名和属性名有些一致的,可以在resultMap中不写映射关系。

5.动态sql

什么是动态sql:

根据参数的值,判断sql的条件。

name!=null address
select * from 表名 where name=#{name} and address=#{address}
name==null
select * from 表名.

mybatis中动态sql标签有哪些?

if标签--单条件判断

//如果name不为null则按照name查询 如果为null则查询所有
    public List<Account> findByCondition(@Param("name")String name,@Param("money") Double money);

 
    <select id="findByCondition" resultType="com.ykq.entity.Account">
        select * from account where 1=1
        <if test="name!=null and name!=''">
             and  name=#{name}
        </if>
        <if test="money!=null">
             and  money=#{money}
        </if>
    </select>

choose标签 多条件分支判断

<select id="findByCondition02" resultType="com.ykq.entity.Account">
        select * from account where 1=1
        <choose>
             <when test="name!=null and name!=''">
                 and  name=#{name}
             </when>
            <when test="money!=null">
                and  money=#{money}
            </when>
            <otherwise>
                and isdeleted=0
            </otherwise>
        </choose>
    </select>

where标签

面的sql都加了 where 1=1 ,如果不使用where 1=1 那么你的动态sql可能会出错。 能不能不加where 1=1? 可以 可以使用where标签,作用:可以自动为你添加where关键字,并且可以帮你去除第一个and \ or。

 <select id="findByCondition" resultType="com.ykq.entity.Account">
        select * from account
        <where>
            <if test="name!=null and name!=''">
                 and  name=#{name}
            </if>
            <if test="money!=null">
                 and  money=#{money}
            </if>
        </where>
    </select>

set标签

配合if标签使用,一般用在修改语句。若传递的参数值为null,那么不修改该列的值。

foreach(循环)标签

循环标签,可以处理一些动态的批量任务,如批量添加、查询、删除等。可以传入一个数组或者一个list集合,然后通过foreach标签将集合内的条件,一个个的放入sql语句,从而实现动态的批量处理效果。

 <!--foreach 查询-->
 <!-- 若使用的为数组array  为集合 那么就用list
        collection:类型
        item:数组中每个元素赋值的变量名
        open: 以谁开始
        close:以谁结束
        separator:分割符
    -->
    <select id="findIds" resultMap="StuMapper">
        select <include refid="zz"/> from t_stu where id in
            <foreach collection="array" item="id" open="(" close=")" separator=",">
                #{id}
            </foreach>
    </select>

sql片段

执行查询语句时不建议使用select *, 建议把查询的列写出。

6.通过dao和映射文件的关联来完成crud

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zsy</groupId>
    <artifactId>mybatis08</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!--mybatis依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.9</version>
        </dependency>
        <!--mysql依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>
        <!--junit依赖-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <!--lombok依赖-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
        </dependency>
        <!--log4j依赖-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>
</project>

创建实体类:

package com.zsy.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author : zhou
 * @date : 20:47 2022/6/1
 * 使用 lombok自动生成
 */

@Data//get、set和重写toString方法
@NoArgsConstructor//无参构造
@AllArgsConstructor//有参构造
public class Student {
    private Integer id;
    private String name;
    private Integer age;
    private String sex;
}

dao:

package com.zsy.dao;

import com.zsy.entity.Student;
import org.apache.ibatis.annotations.Param;

import java.util.List;

/**
 * @author : zhou
 * @date : 20:50 2022/6/1
 */
public interface StudentDao {

    //查询
    public List<Student> findAll();

    //条件查询
    public Student findBy(@Param("stu_name")String stu_name,@Param("stu_age")Integer stu_age);

    //添加
    public void add(Student s);

    //修改
    public void upd(Student s);

    //删除
    public void del(int id);
}

xml:

<?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">
<!--namespace:命名空间
       可以随便起名,但是后期我们要求命名空间的值必须和所对应的dao相同
-->
<mapper namespace="com.zsy.dao.StudentDao">

    <resultMap id="ResultMap" type="com.zsy.entity.Student">
        <!--主键的映射关系 column:列名 property:属性名-->
        <id column="stu_id" property="id"/>
        <!--普通的映射关系-->
        <result column="stu_name" property="name"/>
        <result column="stu_age" property="age"/>
    </resultMap>

    <!--添加-->
    <insert id="add" parameterType="com.zsy.entity.Student">
        insert into t_stu values(null,#{name},#{age},#{sex})
    </insert>

    <!--修改-->
    <update id="upd" parameterType="com.zsy.entity.Student">
        update t_stu
            <set>
                <if test="name!=null and name!=''">
                    stu_name=#{name},
                </if>
                <if test="age!=null and age!=''">
                    stu_age=#{age},
                </if>
                <if test="sex!=null and sex!=''">
                    sex=#{sex}
                </if>
            </set>
            where stu_id=#{id}
    </update>

    <!--删除-->
    <delete id="del" parameterType="com.zsy.entity.Student">
        delete from t_stu where stu_id=#{id}
    </delete>

    <!--查询所有信息-->

    <select id="findAll" resultMap="ResultMap">
        select * from t_stu
    </select>

    <!--条件查询-->
    <select id="findBy" resultMap="ResultMap">
        select * from t_stu
            <where>
                <if test="stu_name!=null and stu_name=''">
                    and stu_name=#{stu_name}
                </if>
                <if test="stu_age!=null and stu_age=''">
                    and stu_age=#{stu_age}
                </if>
            </where>
    </select>
</mapper>

测试:

package com.zsy.test;

import com.zsy.dao.StudentDao;
import com.zsy.entity.Student;
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 org.junit.Test;

import java.io.Reader;
import java.util.List;

/**
 * @author : zhou
 * @date : 20:50 2022/6/1
 */
public class StudentTest {

    //查询所有信息
    @Test
    public void findAll() throws Exception{
        Reader reader = Resources.getResourceAsReader("mybatis.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
        SqlSession session = factory.openSession();
        StudentDao sd = session.getMapper(StudentDao.class);
        List<Student> l = sd.findAll();
        System.out.println(l);

        session.close();

    }

    //条件查询
    @Test
    public void findBy() throws Exception{
        Reader reader = Resources.getResourceAsReader("mybatis.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
        SqlSession session = factory.openSession();
        StudentDao sd = session.getMapper(StudentDao.class);
        Student s = sd.findBy("张角",40);
        System.out.println(s);

        session.close();

    }

    //添加
    @Test
    public void insert() throws Exception{
        Reader reader = Resources.getResourceAsReader("mybatis.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
        SqlSession session = factory.openSession();
        StudentDao sd = session.getMapper(StudentDao.class);
        Student s = new Student();
        s.setName("赵云");
        s.setAge(25);
        s.setSex("男");
        sd.add(s);

        session.commit();
        session.close();

    }

    //修改
    @Test
    public void update() throws Exception{
        Reader reader = Resources.getResourceAsReader("mybatis.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
        SqlSession session = factory.openSession();
        StudentDao sd = session.getMapper(StudentDao.class);
        Student s = new Student(2,"貂蝉",18,"女");
        sd.upd(s);

        session.commit();
        session.close();

    }

    //删除
    @Test
    public void delete() throws Exception{
        Reader reader = Resources.getResourceAsReader("mybatis.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
        SqlSession session = factory.openSession();
        StudentDao sd = session.getMapper(StudentDao.class);
        sd.del(5);

        session.commit();
        session.close();

    }
}

7.mybatis映射文件处理特殊字符.

在mapper中写sql语句时,会遇到一些特殊的字符,会与sql代码会产生冲突,如sql中的语句:

  小于号,就是一种特殊字符。

解决方法一:转义标签 &lt; 

方法二:<![CDATA[sql]]>

<![CDATA[ sql 语句 ]]>标记,将sql语句包裹住,不被解析器解析

9.联表查询

多对一 : 从多的一方来查询一的一方。

根据员工id查询员工信息并携带部门信息。

方法一:

创建实体类:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Emp {
    private Integer id;
    private String name;
    private Integer age;
    private String job;
    private Integer deptId;
    private Dept dept;
}




@Data
@NoArgsConstructor
@AllArgsConstructor
public class Dept {
    private Integer id;
    private String name;
}

EmpMapper.xml

<?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">
<!--namespace:命名空间
       命名空间的值必须和所对应的dao相同
-->
<mapper namespace="com.zsy.dao.EmpDao">

    <sql id="ed">
        e.id,e.name,e.age,e.job,e.dept_id,d.id did,d.name dname
    </sql>

    <resultMap id="empMap" type="com.zsy.entity.Emp">
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="age" property="age"/>
        <result column="job" property="job"/>
        <result column="dept_id" property="deptId"/>
        <!--association: 表示一的一方
                property: 它表示属性名
                javaType: 该属性名对应的数据类型
          -->
        <association property="dept" javaType="com.zsy.entity.Dept">
            <id column="did" property="id"/>
            <result column="dname" property="name"/>
        </association>
    </resultMap>
    <!--联表查询-->
    <select id="findId" resultMap="empMap">
        select <include refid="ed"/> from tb_emp e join tb_dept d on e.dept_id=d.id where e.id=#{id}
    </select>
</mapper>

 方法二:

用map封装返回类型  -----不推荐。

public Map findById(Integer id);
<select id="findId" resultType="java.util.Map">
        select <include refid="empAndDept"/> from tb_emp e join tb_dept d on e.dept_id = d.id where e.id=#{id}
</select>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Naaaaa.a

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

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

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

打赏作者

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

抵扣说明:

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

余额充值