关系型数据库和SQL是经受时间考验和验证的数据存储机制。和其他的ORM框架如Hibernate不同,MyBatis鼓励开发者可以直接使用数据库,而不是将其对开发者隐藏,因为这样可以充分发挥数据库服务器所提供的SQL语句的巨大威力。与此同时,MyBaits消除了书写大量冗余代码的痛苦,它让使用SQL更容易。在代码里直接嵌套SQL语句是很差的编码实践,并且维护起来困难。MyBaits使用了映射文件或注解来配置SQL语句。
※1 映射器文件和映射器接口
我们已经看见了一些在映射器配置文件中配置基本的映射语句,以及怎样
使用SqlSession对象调用它们的例子。现在让我们看一下在
com.briup.mappers包中的StudentMapper.xml 配置文件内,
是如何配置id为”findStudentById”的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="com.briup.mappers.StudentMapper">
<select id="findStudentById" parameterType="int" resultType="Student">
select stud_id as studId, name, email, dob
from students where stud_id=#{studId}
</select>
</mapper>
我们可以通过下列代码调用findStudentById映射的SQL语句:
public Student findStudentById(Integer studId) {
SqlSession sqlSession = MyBatisSqlSessionFactory.openSession();
try{
Student student = sqlSession.selectOne("com.briup.mappers.StudentMapper.findStudentById", studId);
return student;
}
finally {
sql Session.close();
}
}
我们可以通过字符串(字符串形式为:映射器配置文件所在的包名的
namespace + 在文件内定义的语句id,如上,即包名com.briup.mappers.StudentMapper
和语句id的值findStudentById组成)调用映射的SQL语句,但是这
种方式容易出错。你需要检查映射器配置文件中的定义,以保证你的输入
参数类型和结果返回类型是有效的。
【重点部分:】
MyBatis通过使用映射器Mapper接口提供了更好的调用映射语句的方法。
一旦我们通过映射器配置文件配置了映射语句,我们可以创建一个完全对应
的一个映射器接口,xml映射文件中的namespace属性值和映射接口的全
限定名需要保持一致。映射器接口中的方法签名也跟映射器配置文件中完全
对应:方法名和配置文件中id值一致;方法参数类型和parameterType
属性值一种;方法返回值类型和returnType属性值一致。
上述的StudentMapper.xml文件,我们可以创建一个映射器接口StudentMapper.java如下:
package com.briup.mappers;
public interface StudentMapper{
Student findStudentById(Integer id);
}
在Student Mapper.xml映射器配置文件中,其名空间namespace应该跟StudentMapper接口的全限定名保持一致。另外,StudentMapper.xml中语句id, parameterType,returnType 应该分别和StudentMapper接口中的方法名,参数类型,返回值相对应。
使用映射器接口我们可以以类型安全的形式调用调用映射语句。如下所示:
public Student findStudentById(Integer studId){
SqlSession sqlSession = MyBatisSqlSessionFactory.openSession();
try {
StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
return student Mapper.findStudentById(studId);
}
finally {
sqlSession.close();
}
}
※ 2 映射语句
MyBatis提供了多种元素来配置不同类型的语句,如SELECT,INSERT,UPDATE,DELETE。
让我们看看如何具体配置映射语句
2.1 INSERT 插入语句
一个INSERT语句可以在<insert>标签元素在映射器XML配置文件中配置,如下所示:
<insert id="insertStudent" parameterType="Student">
INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL, PHONE) VALUES(#{studId},#{name},#{email},#{phone})
</insert>
这里我们设置一个ID属性为insertStudent,可以在名空间 com.briup.mappers.StudentMapper.insertStudent中唯一标识该sql语句。parameterType 属性是一个完全限定类名或者是一个类型别名(alias)。
我们可以如下调用这个语句:
int count = sqlSession.insert("com.briup.mappers.StudentMapper.insertStudent", student);
sqlSession.insert() 方法返回执行 INSERT 语句后所影响的行数。
如果不使用名空间(namespace)和语句 id 来调用映射语句,你可以通过创建一个映射器Mapper 接口,并以类型安全的方式调用方法,如下所示:
package com.briup.mappers;
public interface Student Mapper{
int insertStudent(Student student);
}
你可以如下调用insertStudent映射语句:
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
int count = mapper.insertStudent(student);
自动生成主键:
在上述的INSERT语句中,我们为可以自动生成(auto-generated)主键的列 STUD_ID 插入值。我们可以使用useGeneratedKeys和keyProperty属性让数据库生成auto_increment列的值,并将生成的值设置到其中一个输入对象属性内,如下所示:
<insert id="insertStudent" parameterType="Student" useGeneratedKeys="true" keyProperty="studId">
INSERT INTO STUDENTS(NAME, EMAIL, PHONE) VALUES(#{name},#{email},#{phone})
</insert>
这里STUD_ID列值将会被数据库自动生成(如mysql),并且生成的值会被设置到student对象的studId属性上。
但是有些数据库如Oracle并不支持AUTO_INCREMENT列,其使用序列(SEQUENCE)来生成主键值。假设我们有一个名为my_seq的序列来生成SUTD_ID主键值。使用如下代码来生成主键:
drop sequence my_seq;
create sequence my_seq;
<insert id="insertStudent" parameterType="Student">
<selectKey keyProperty="studId" resultType="int" order="BEFORE">
SELECT my_seq.nextval FROM DUAL
</selectKey>
INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL, PHONE)
VALUES(#{studId},#{name},#{email},#{phone})
</insert>
这里我们使用了<selectKey>子元素来生成主键值,并将值保存到Student对象的studId 属性上。属性order=“before”表示MyBatis将取得序列的下一个值作为主键值,并且在执行INSERT语句之前将值设置到studId属性上。
注:SelectKey需要注意order属性,像MySQL、SQLServer等一类支持自动增长类型的数据库中,order需要设置为after才会取到正确的值。
像Oracle这样取序列的情况,需要设置为before,否则会报错。
2.2 UPDATE 更新语句
一个UPDATE SQL语句可以在<update>元素在映射器XML配置文件中配置,如下所示: