MyBatis学习总结(四):MyBatis动态sql之<select>、<insert>、<update>、<delete>标签

1、<select>元素

<select> 元素用于映射 SQL 的 select 语句,其示例代码如下:

    <!-- 根据id查询用户   -->
    <select id="findById" parameterType="Integer" resultType="com.day1.entity.User">
        select * from t_user where id = #{id}
    </select>

 上述示例代码中,id 的值是唯一标识符,它接收一个 Integer 类型的参数,返回User 类型的对象,结果集自动映射到 User 属性。

<select> 元素除了有上述示例代码中的几个属性以外,还有一些常用的属性,如下表:

属性名称 描 述
id 它和 Mapper 的命名空间组合起来使用,是唯一标识符,供 MyBatis 调用
parameterType 表示传入 SQL 语句的参数类型的全限定名或别名。它是一个可选属性,MyBatis 能推断出具体传入语句的参数
resultType SQL 语句执行后返回的类型(全限定名或者别名)。如果是集合类型,返回的是集合元素的类型,返回时可以使用 resultType 或 resultMap 之一
resultMap 它是映射集的引用,与 <resultMap> 元素一起使用,返回时可以使用 resultType 或 resultMap 之一
flushCache 用于设置在调用 SQL 语句后是否要求 MyBatis 清空之前查询的本地缓存和二级缓存,默认值为 false,如果设置为 true,则任何时候只要 SQL 语句被调用都将清空本地缓存和二级缓存
useCache 启动二级缓存的开关,默认值为 true,表示将査询结果存入二级缓存中
timeout
用于设置超时参数,单位是秒(s),超时将抛出异常
fetchSize 获取记录的总条数设定
statementType 告诉 MyBatis 使用哪个 JDBC 的 Statement 工作,取值为 STATEMENT(Statement)、 PREPARED(PreparedStatement)、CALLABLE(CallableStatement)
resultSetType 这是针对 JDBC 的 ResultSet 接口而言,其值可设置为 FORWARD_ONLY(只允许向前访问)、SCROLL_SENSITIVE(双向滚动,但不及时更新)、SCROLLJNSENSITIVE(双向滚动,及时更新)

 然而在实际开发中,有可能需要传递多个参数,那么如何实现呢?我们可以通过两种方式来完成:使用Map接口和使用JavaBean。

方式一:使用Map接口传递多个参数。

(1)创建数据库表,并插入数据

CREATE TABLE `t_student` (
  `username` varchar(20) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `address` varchar(20) DEFAULT NULL
);
insert into t_student values("tom", 23 ,"陕西");
 insert into t_student values("王刚", 43,"安徽");
 insert into t_student values("张伟", 43 ,"北京");
 insert into t_student values("刘倩", 19,"北京");
 insert into t_student values("陆风", 21,"上海");
 insert into t_student values("齐菲", 56,"河北");
 insert into t_student values("王可", 56,"河南");


(2)创建Student类

public class Student {
    private String username;
    private Integer age;
    private String address;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Integer getAge() {
        return age;
    }

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

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Student{" +
                "username='" + username + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                '}';
    }
}

(3)创建IStudentDao

public interface IStudentDao {
    List<Student> findStudent(Map<String, Object> map);
}

 (4)创建studentMapper.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:指定了唯一的命名空间-->
<mapper namespace="com.day1.dao.IStudentDao">
    <!--  查找年龄大于30且名字开头为张的学生  -->
    <select id="findStudent" resultType="com.day1.entity.Student">
        select * from t_student where age > #{age} and username like #{nstart};
    </select>
</mapper>

 (5)在SqlMapperConfig.xml中指定映射的配置文件

<mapper resource="com/day1/studentMapper.xml"></mapper>

(6)测试。

    @Test
    public void testFindStudent() throws IOException {
        //1、读取配置文件
        InputStream in = Resources.getResourceAsStream("SqlMapperConfig.xml");
        //2、创建SqlSessionFactory工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        //3、使用工厂生产SqlSession对象
        SqlSession sqlSession = factory.openSession();
        //4、使用SqlSession创建dao接口的代理对象
        IStudentDao studentDao = sqlSession.getMapper(IStudentDao.class);
        //5、使用代理对象执行方案
        Map<String, Object> map = new HashMap<>();
        map.put("age", 30);
        map.put("nstart","张%");
        List<Student> students = studentDao.findStudent(map);
        for(Student stu : students){
            System.out.println(stu);
        }
        //6、释放资源
        sqlSession.close();
        in.close();
    }

方式二:使用JavaBean传递多个参数

(1)IStudentDao添加方法findStudentNewWay();

List<Student> findStudentNewWay(Student student);

(2)在studentMapper.xml中添加查询语句。

<select id="findStudentNewWay" resultType="com.day1.entity.Student" parameterType="com.day1.entity.Student">
        select * from t_student where age > #{age} and username like #{username};
    </select>

(3)进行测试。

    @Test
    public void testFindStudent2() throws IOException {
        //1、读取配置文件
        InputStream in = Resources.getResourceAsStream("SqlMapperConfig.xml");
        //2、创建SqlSessionFactory工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        //3、使用工厂生产SqlSession对象
        SqlSession sqlSession = factory.openSession();
        //4、使用SqlSession创建dao接口的代理对象
        IStudentDao studentDao = sqlSession.getMapper(IStudentDao.class);
        //5、使用代理对象执行方案
        Student student = new Student();
        student.setAge(30);
        student.setUsername("张%");
        List<Student> students = studentDao.findStudentNewWay(student);
        for(Student stu : students){
            System.out.println(stu);
        }
        //6、释放资源
        sqlSession.close();
        in.close();
    }

建议:如果参数较少,建议选择 Map;如果参数较多,建议选择 Java Bean。

2、<insert>元素

<insert> 元素用于映射插入语句,MyBatis 执行完一条插入语句后将返回一个整数表示其影响的行数。它的属性与 <select> 元素的属性大部分相同,有以下几个特有属性:

  • keyProperty:该属性的作用是将插入或更新操作时的返回值赋给 PO 类的某个属性,通常会设置为主键对应的属性。如果是联合主键,可以将多个值用逗号隔开。
  • keyColumn:该属性用于设置第几列是主键,当主键列不是表中的第 1 列时需要设置。如果是联合主键,可以将多个值用逗号隔开。
  • useGeneratedKeys:该属性将使 MyBatis 使用 JDBC 的 getGeneratedKeys()方法获取由数据库内部产生的主键,例如 MySQL、SQL Server 等自动递增的字段,其默认值为 false。

如果在实际开发中需要用主键关联其他业务,有两种方式可以完成,第一种方式是通过数据库表的自增主键完成;第二种方式可以使用 MyBatis 的 <selectKey> 元素来自定义生成主键。具体配置示例代码如下:

    <!--  添加用户  -->
    <insert id="addUser" parameterType="com.day1.entity.User">
        <!--
        keyProperty:将查询到主键值设置到 parameterType 指定的对象的那个属性
        keyColumn:数据库中的列名
        order:SELECT LAST_INSERT_ID() 执行顺序,相对于 insert 语句来说它的执行顺序
        resultType:指定 SELECTLAST_INSERT_ID() 的结果类型
         -->
        <selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
            select last_insert_id();
        </selectKey>
        insert into t_user(username, password) values(#{username}, #{password});
    </insert>

在执行上述示例代码时,<selectKey> 元素首先被执行,该元素通过自定义的语句设置数据表的主键,然后执行插入语句。

<selectKey> 元素的 keyProperty 属性指定了新生主键值返回给 PO 类的哪个属性。

  • order 属性可以设置为 BEFORE 或 AFTER。
  • BEFORE 表示先执行 <selectKey> 元素然后执行插入语句。
  • AFTER 表示先执行插入语句再执行 <selectKey> 元素。

3、<update>与<delete>元素

<update> 和 <delete> 元素比较简单,它们的属性和 <insert> 元素、<select> 元素的属性差不多,执行后也返回一个整数,表示影响了数据库的记录行数。配置示例代码如下:

    <!--  删除用户  -->
    <delete id="deleteById" parameterType="int">
        delete from t_user where id = #{id}
    </delete>
    <!--  更新用户信息  -->
    <update id="updateUser" parameterType="com.day1.entity.User">
        update t_user set username =#{username}, password= #{password} where id = #{id}
    </update>

4、sql元素

sql元素标签用来定义可重复使用的SQL代码片段,使用时只需要用include元素标签引用即可,最终达到SQL语句重用的目的;同时它可以被静态地(在加载参数) 参数化,不同的属性值通过包含的实例变化,使用如下:

    <!--    建立sql片段-->
    <sql id="query_student">
        <if test="username != null and username !=''">
            and username like '%${username}%'
        </if>
    </sql>
    <!--    使用include引用sql片段-->
    <select id="findStudentList" parameterType="com.day1.entity.Student" resultType="com.day1.entity.Student">
        select * from t_student
        <where>
            <include refid="query_student"/>
        </where>
    </select>

猜你喜欢

转载自blog.csdn.net/weixin_47382783/article/details/113816962