Mybatis与其它ORM框架的一个很大的不同之处就在于,Mybatis能够充分地使用SQL语句。
本篇博客来详细介绍在Mybatis中如何进行SQL映射。

映射配置文件和映射接口

假设使用了下面的方式来定义一个SQL映射

<?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">
<mapper namespace="code.test.mybatis.mybatis_demo.StudentMapper">
    <select id="findStudentById" parameterType="int" 
    resultType="blog.zdk.mybatis.mybatis_beginning_demo.Student">
        SELECT STUD_ID AS STUDID, NAME, EMAIL, DOB
        FROM STUDENTS WHERE STUD_ID=#{Id}
    </select>
</mapper>

然后通过这种方式来与数据库交互

SqlSession sqlSession = MyBatisSqlSessionFactory.openSession();
Student student = sqlSession.selectOne("code.test.mybatis.mybatis_demo.StudentMapper.findStudentById", 1);

sqlSession.selectOne("code.test.mybatis.mybatis_demo.StudentMapper.findStudentById", 1)这行代码是通过一个很长的字符串来调用的,我担心把字符串写错,mybatis是否支持通过强类型的方式来调用某个SQL代码?
强类型的调用方式可以很好地利用编译器的纠错功能。
我们新建一个与映射配置文件的namespace相同的接口,在接口中定义一个与SQL语句对应的id一样的方法名,参数签名和返回值类型也要一致,如下

package code.test.mybatis.mybatis_demo;
import java.util.List;

public interface StudentMapper {
    Student findStudentById(Integer id);
}

然后,通过强类型的方式来调用

StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
return studentMapper.findStudentById(1);

这种方式与通过长长的字符串来调用相比,是一种更好的编程体验。

定义SQL语句

我们在映射配置文件中可以通过<insert><update><delete><select>元素来分别定义插入、更新、删除、查询。

<?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">
<mapper namespace="code.test.mybatis.mybatis_demo.StudentMapper">
    <select id="findAllStudents" resultType="Student">
        SELECT * FROM STUDENTS
    </select>
    <select id="findStudentById" parameterType="int" 
    resultType="Student">
        SELECT STUD_ID AS STUDID, NAME, EMAIL, DOB
        FROM STUDENTS WHERE STUD_ID=#{Id}
    </select>
    <!-- 如果数据表的主键是自增长的,则需要指定useGeneratedKeys属性和keyProperty属性(Java对象的属性) -->
    <insert id="insertStudent" parameterType="Student" useGeneratedKeys="true" keyProperty="studId">
        INSERT INTO STUDENTS(NAME,EMAIL,DOB)
        VALUES(#{name},#{email},#{dob})
    </insert>
    <update id="updateStudent" parameterType="Student">
        UPDATE STUDENTS SET NAME=#{name},EMAIL=#{email},DOB=#{dob}
        WHERE STUD_ID=#{studId}
    </update>
    <delete id="deleteStudent" parameterType="int">
        DELETE FROM STUDENTS WHERE STUD_ID=#{studId}
    </delete>
</mapper>

定义映射接口

package code.test.mybatis.mybatis_demo;

import java.util.List;
import blog.zdk.mybatis.mybatis_beginning_demo.Student;

public interface StudentMapper {

    public List<Student> findAllStudents();

    public Student findStudentById(int id);

    public int insertStudent(Student student) ;

    public int deleteStudent(int id);
}

调用方法如下:

SqlSession sqlSession = MyBatisSqlSessionFactory.openSession();
try {
    //通过字符串调用,仅供参考
    //Student student = sqlSession.selectOne("code.test.mybatis.mybatis_demo.StudentMapper.findStudentById", 1);
    //获取映射接口对象
    StudentMapper studentMapper=sqlSession.getMapper(StudentMapper.class);
    //调用select语句
    Student student=studentMapper.findStudentById(1);
    System.out.println("name=" + student.getName());
    System.out.println("email=" + student.getEmail());
    System.out.println("birth=" + student.getDob());
    //调用insert语句
    Student newStudent=new Student();
    newStudent.setName("kai");
    newStudent.setEmail("kai@163.com");
    SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd");
    String dateString="1994-01-01";
    newStudent.setDob(dateFormat.parse(dateString));
    int rows= studentMapper.insertStudent(newStudent);
    sqlSession.commit();
    System.out.println(rows);
    System.out.println(newStudent.getStudId());
    //调用delete语句
    rows= studentMapper.deleteStudent(3);
    System.out.println(rows);
    sqlSession.commit();

} catch (Exception e) {
    e.printStackTrace();
}finally {
    sqlSession.close();
}

注意:

  • 如果在配置文件中定义的transactionManager的type=”JDBC”的话,除了select语句以外,其他的SQL语句最后需要调用sqlSession.commit();,否则数据将不会持久化。如果type=”MANAGED”,则无需调用commint()方法。
  • 在定义SQL语句时,如果只有一个普通类型的参数,则这个参数的名字可以任意指定,例如:将WHERE STUD_ID=#{Id}修改为WHERE STUD_ID=#{XXX},结果不受影响。

SQL语句中包含’<’等特殊符号

如果sql中包含’<’等特殊符号,则执行该sql时会报错,此时需要稍作修改

<select id="findStudentByScore" parameterType="int" 
    resultType="Student">
    <![CDATA[
    SELECT STUD_ID AS STUDID, NAME, EMAIL, DOB
    FROM STUDENTS WHERE STUD_ID < #{score}
    ]]>
</select>