MyBatis注解
注解 | 目标 | 相应的XML | 描述 |
@CacheNamespace | 类 | <cache> | 为给定的命名空间(比如类)配置缓存。属性: implemetation,eviction, flushInterval , size 和 readWrite 。 |
@CacheNamespaceRef | 类 | <cacheRef> | 参照另外一个命名空间的缓存来使用。 属性:value,也就是类的完全限定名。 |
@ConstructorArgs | 方法 | <constructor> | 收集一组结果传递给对象构造方法。 属性:value,是形式参数的数组 |
@Arg | 方法 | <arg> <idArg>
| 单独的构造方法参数,是ConstructorArgs 集合的一部分。属性:id,column,javaType,typeHandler。 id属性是布尔值,来标识用于比较的属性,和<idArg>XML 元素相似 |
@TypeDiscriminator | 方法 | <discriminator> | 一组实例值被用来决定结果映射的表 现。属性:Column, javaType , jdbcType typeHandler,cases。 cases属性就是实例的数组。 |
@Case | 方法 | <case> | 单独实例的值和它对应的映射。属性:value ,type ,results 。 Results 属性是结果数组,因此这个注解和实际的ResultMap 很相似,由下面的 Results注解指定 |
@Results | 方法 | <resultMap> | 结果映射的列表,包含了一个特别结果 列如何被映射到属性或字段的详情。 属性:value ,是Result注解的数组 |
@Result | 方法 | <result> <id> | 在列和属性或字段之间的单独结果映 射。属性:id ,column , property , javaType ,jdbcType ,type Handler , one,many。id 属性是一个布尔值,表 示了应该被用于比较的属性。one 属性是单独的联系,和 <association> 相似,而many 属性是对集合而言的,和 <collection>相似。 |
@One | 方法 | <association> | 复杂类型的单独属性值映射。属性: select,已映射语句(也就是映射器方 法)的完全限定名,它可以加载合适类 型的实例。注意:联合映射在注解 API 中是不支持的。 |
@Many | 方法 | <collection> | 复杂类型的集合属性映射。属性: select,是映射器方法的完全限定名,它可加载合适类型的一组实例。注意:联合映射在 Java注解中是不支持的。 |
@Options | 方法 | 映射语句的属性 | 这个注解提供访问交换和配置选项的宽广范围,它们通常在映射语句上作为属性出现。而不是将每条语句注解变复杂,Options 注解提供连贯清晰的方式来访问它们。属性:useCache=true, flushCache=false, resultSetType=FORWARD_ONLY, statementType=PREPARED, fetchSize= -1,timeout=-1 , useGeneratedKeys=false , keyProperty=”id“。 理解Java 注解是很重要的,因为没有办法来指定“null ”作为值。因此,一旦你使用了 Options注解,语句就受所有默认值的支配。要注意什么样的默认值来避免不期望的行为 |
@Insert @Update @Delete | 方法 | <insert> <update> <delete> | 这些注解中的每一个代表了执行的真实 SQL。它们每一个都使用字符串数组(或单独的字符串)。如果传递的是字符串数组,它们由每个分隔它们的单独空间串联起来。属性:value,这是字符串数组用来组成单独的SQL语句 |
@InsertProvider @UpdateProvider @DeleteProvider @SelectProvider | 方法 | <insert> <update> <delete> <select> 允许创建动态 SQL。 | 这些可选的SQL注解允许你指定一个 类名和一个方法在执行时来返回运行 的SQL。基于执行的映射语句, MyBatis 会实例化这个类,然后执行由 provider 指定的方法. 这个方法可以选择性的接 受参数对象作为它的唯一参数,但是必 须只指定该参数或者没有参数。属性: type,method。type 属性是类的完全限定名。method 是该类中的那个方法名。 |
@Param | 参数 | N/A | 当映射器方法需多个参数,这个注解可以被应用于映射器方法参数来给每个参数一个名字。否则,多参数将会以它们的顺序位置来被命名。比如 #{1},#{2} 等,这是默认的。 使用@Param(“person”),SQL中参数应该被命名为#{person}。 |
使用方法
1.insert方法
package com.mybatis3.mappers;
public interface StudentMapper
{
@Insert("INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL,ADDR_ID, PHONE)
VALUES(#{studId},#{name},#{email},#{address.addrId},#{phone})")
int insertStudent(Student student);
使用了@Insert注解的方法将返回insert语句执行后影响的行数。
2.自动生成主键
@Insert("INSERT INTO STUDENTS(NAME,EMAIL,ADDR_ID, PHONE)
VALUES(#{name},#{email},#{address.addrId},#{phone})")
@Options(useGeneratedKeys = true, keyProperty = "studId")
int insertStudent(Student student);
这里stu_id主键列值将会通过MySQL数据库自动生成。并且生成的值将会被设置到student对象的studId属性中。
mapper.insertStudent(student);
int studentId = student.getStudId();
@Update("UPDATE STUDENTS SET NAME=#{name}, EMAIL=#{email},
PHONE=#{phone} WHERE STUD_ID=#{studId}")
int updateStudent(Student student);
使用了@Update的方法将会返回执行了update语句后影响的行数。
@Delete("DELETE FROM STUDENTS WHERE STUD_ID=#{studId}")
int deleteStudent(int studId);
使用了@Delete的方法将会返回执行了update语句后影响的行数。
5.select方法
public interface StudentMapper
{
@Select("SELECT STUD_ID AS STUDID, NAME, EMAIL, PHONE FROM
STUDENTS WHERE STUD_ID=#{studId}")
Student findStudentById(Integer studId);
}
@Select("SELECT * FROM STUDENTS WHERE STUD_ID=#{studId}")
@Results(
{
@Result(id = true, column = "stud_id", property = "studId"),
@Result(column = "name", property = "name"),
@Result(column = "email", property = "email"),
@Result(column = "addr_id", property = "address.addrId")
})
Student findStudentById(int studId);
@Select("SELECT * FROM STUDENTS")
@Results(
{
@Result(id = true, column = "stud_id", property = "studId"),
@Result(column = "name", property = "name"),
@Result(column = "email", property = "email"),
@Result(column = "addr_id", property = "address.addrId")
})
List<Student> findAllStudents();
<mapper namespace="com.mybatis3.mappers.StudentMapper">
<resultMap type="Student" id="StudentResult">
<id property="studId" column="stud_id" />
<result property="name" column="name" />
<result property="email" column="email" />
<result property="phone" column="phone" />
</resultMap>
</mapper>
@Select("SELECT * FROM STUDENTS WHERE STUD_ID=#{studId}")
@ResultMap("com.mybatis3.mappers.StudentMapper.StudentResult")
Student findStudentById(int studId);
@Select("SELECT * FROM STUDENTS")
@ResultMap("com.mybatis3.mappers.StudentMapper.StudentResult")
List<Student> findAllStudents();
@Select("SELECT ADDR_ID AS ADDRID, STREET, CITY, STATE, ZIP, COUNTRY
FROM ADDRESSES WHERE ADDR_ID=#{id}")
Address findAddressById(int id);
@Select("SELECT * FROM STUDENTS WHERE STUD_ID=#{studId} ")
@Results(
{
@Result(id = true, column = "stud_id", property = "studId"),
@Result(column = "name", property = "name"),
@Result(column = "email", property = "email"),
@Result(property = "address", column = "addr_id",
one = @One(select = "com.mybatis3.mappers.StudentMapper.
findAddressById"))
})
Student selectStudentWithAddress(int studId);
这里我们使用了@One注解的select属性来指定一个使用了完全限定名的方法上,该方法会返回一个Address对象。使用column=”addr_id”,则STUEDNTS表中列addr_id的值将会作为输入参数传递给findAddressById()方法。如果@OneSELECT查询返回了多行结果,则会抛出TooManyResultsException异常。
<mapper namespace="com.mybatis3.mappers.StudentMapper">
<resultMap type="Address" id="AddressResult">
<id property="addrId" column="addr_id" />
<result property="street" column="street" />
<result property="city" column="city" />
<result property="state" column="state" />
<result property="zip" column="zip" />
<result property="country" column="country" />
</resultMap>
<resultMap type="Student" id="StudentWithAddressResult">
<id property="studId" column="stud_id" />
<result property="name" column="name" />
<result property="email" column="email" />
<association property="address" resultMap="AddressResult" />
</resultMap>
</mapper>
@Select("select stud_id, name, email, a.addr_id, street, city,
state, zip, country" + " FROM students s left outer join addresses a on s.addr_id=a.addr_id" + " where stud_id=#{studId} ") @ResultMap("com.mybatis3.mappers.StudentMapper. StudentWithAddressResult") Student selectStudentWithAddress(int id);
9.一对多映射
@Select("select addr_id as addrId, street, city, state, zip,
country from addresses where addr_id=#{id}")
Address findAddressById(int id);
@Select("select * from courses where tutor_id=#{tutorId}")
@Results(
{
@Result(id = true, column = "course_id", property = "courseId"),
@Result(column = "name", property = "name"),
@Result(column = "description", property = "description"),
@Result(column = "start_date" property = "startDate"),
@Result(column = "end_date" property = "endDate")
})
List<Course> findCoursesByTutorId(int tutorId);
@Select("SELECT tutor_id, name as tutor_name, email, addr_id
FROM tutors where tutor_id=#{tutorId}")
@Results(
{
@Result(id = true, column = "tutor_id", property = "tutorId"),
@Result(column = "tutor_name", property = "name"),
@Result(column = "email", property = "email"),
@Result(property = "address", column = "addr_id",
one = @One(select = " com.mybatis3.
mappers.TutorMapper.findAddressById")),
@Result(property = "courses", column = "tutor_id",
many = @Many(select = "com.mybatis3.mappers.TutorMapper.
findCoursesByTutorId"))
})
Tutor findTutorById(int tutorId);
这里我们使用了@Many注解的select属性来指向一个完全限定名称的方法,该方法将返回一个List<Course>对象。使用column=”tutor_id”,TUTORS表中的tutor_id列值将会作为输入参数传递给findCoursesByTutorId()方法。
<mapper namespace="com.mybatis3.mappers.TutorMapper">
<resultMap type="Address" id="AddressResult">
<id property="addrId" column="addr_id" />
<result property="street" column="street" />
<result property="city" column="city" />
<result property="state" column="state" />
<result property="zip" column="zip" />
<result property="country" column="country" />
</resultMap>
<resultMap type="Course" id="CourseResult">
<id column="course_id" property="courseId" />
<result column="name" property="name" />
<result column="description" property="description" />
<result column="start_date" property="startDate" />
<result column="end_date" property="endDate" />
</resultMap>
<resultMap type="Tutor" id="TutorResult">
<id column="tutor_id" property="tutorId" />
<result column="tutor_name" property="name" />
<result column="email" property="email" />
<association property="address" resultMap="AddressResult" />
<collection property="courses" resultMap="CourseResult" />
</resultMap>
</mapper>
@Select("SELECT T.TUTOR_ID, T.NAME AS TUTOR_NAME, EMAIL,
A.ADDR_ID, STREET, CITY, STATE, ZIP, COUNTRY, COURSE_ID, C.NAME,
DESCRIPTION, START_DATE, END_DATE FROM TUTORS T LEFT OUTER
JOIN ADDRESSES A ON T.ADDR_ID=A.ADDR_ID LEFT OUTER JOIN COURSES
C ON T.TUTOR_ID=C.TUTOR_ID WHERE T.TUTOR_ID=#{tutorId}")
@ResultMap("com.mybatis3.mappers.TutorMapper.TutorResult")
Tutor selectTutorById(int tutorId);
1.@SelectProvider
public class TutorDynaSqlProvider
{
public String findTutorByIdSql(int tutorId)
{
return "SELECT TUTOR_ID AS tutorId, NAME, EMAIL FROM TUTORS
WHERE TUTOR_ID=" + tutorId;
}
}
然后创建一个映射语句
@SelectProvider(type=TutorDynaSqlProvider.class, method="findTutorByIdSql")
Tutor findTutorById(int tutorId);
这里我们使用了@SelectProvider来指定了一个类,及其内部的方法,用来提供需要执行的SQL语句。
public class TutorDynaSqlProvider
{
public String findTutorByIdSql(final int tutorId)
{
return new SQL()
{
{
SELECT("tutor_id as tutorId, name, email");
FROM("tutors");
WHERE("tutor_id=" + tutorId);
}
} .toString();
}
}
SQL工具类会处理以合适的空格前缀和后缀来构造SQL语句。
- 无参数
- 和映射器Mapper接口的方法同类型的参数
- java.util.Map
public String findTutorByIdSql()
{
return new SQL()
{
{
SELECT("tutor_id as tutorId, name, email");
FROM("tutors");
WHERE("tutor_id = #{tutorId}");
}
} .toString();
}
这里我们没有使用输入参数构造SQL语句,所以它可以是一个无参方法。
Tutor findTutorById(int tutorId);
这里findTutorById(int)方法只有一个int类型的参数。我们可以定义findTutorByIdSql(int)方法作为SQL provider方法。
public String findTutorByIdSql(final int tutorId)
{
return new SQL()
{
{
SELECT("tutor_id as tutorId, name, email");
FROM("tutors");
WHERE("tutor_id=" + tutorId);
}
} .toString();
}
如果映射器Mapper接口有多个输入参数,我们可以使用参数类型为java.util.Map的方法作为SQLprovider方法。然后映射器Mapper接口方法所有的输入参数将会被放到map中,以param1,param2等等作为key,将输入参数按序作为value。你也可以使用0,1,2等作为key值来取的输入参数。
@SelectProvider(type = TutorDynaSqlProvider.class,
method = "findTutorByNameAndEmailSql")
Tutor findTutorByNameAndEmail(String name, String email);
public String findTutorByNameAndEmailSql(Map<String, Object> map)
{
String name = (String) map.get("param1");
String email = (String) map.get("param2");
//you can also get those values using 0,1 keys
//String name = (String) map.get("0");
//String email = (String) map.get("1");
return new SQL()
{
{
SELECT("tutor_id as tutorId, name, email");
FROM("tutors");
WHERE("name=#{name} AND email=#{email}");
}
} .toString();
}
SQL工具类也提供了其他的方法来表示JOINS,ORDER_BY,GROUP_BY等等。
public class TutorDynaSqlProvider
{
public String selectTutorById()
{
return new SQL()
{
{
SELECT("t.tutor_id, t.name as tutor_name, email");
SELECT("a.addr_id, street, city, state, zip, country");
SELECT("course_id, c.name as course_name, description,
start_date, end_date");
FROM("TUTORS t");
LEFT_OUTER_JOIN("addresses a on t.addr_id=a.addr_id");
LEFT_OUTER_JOIN("courses c on t.tutor_id=c.tutor_id");
WHERE("t.TUTOR_ID = #{id}");
}
} .toString();
}
}
public interface TutorMapper
{
@SelectProvider(type = TutorDynaSqlProvider.class,
method = "selectTutorById")
@ResultMap("com.mybatis3.mappers.TutorMapper.TutorResult")
Tutor selectTutorById(int tutorId);
}
由于没有支持使用内嵌结果ResultMap的一对多关联映射的注解支持,我们可以使用基于XML的<resultMap>配置,然后与@ResultMap映射。
2.@InsertProvider
public class TutorDynaSqlProvider
{
public String insertTutor(final Tutor tutor)
{
return new SQL()
{
{
INSERT_INTO("TUTORS");
if (tutor.getName() != null)
{
VALUES("NAME", "#{name}");
}
if (tutor.getEmail() != null)
{
VALUES("EMAIL", "#{email}");
}
}
} .toString();
}
}
public interface TutorMapper
{
@InsertProvider(type = TutorDynaSqlProvider.class,
method = "insertTutor")
@Options(useGeneratedKeys = true, keyProperty = "tutorId")
int insertTutor(Tutor tutor);
}
public class TutorDynaSqlProvider
{
public String updateTutor(final Tutor tutor)
{
return new SQL()
{
{
UPDATE("TUTORS");
if (tutor.getName() != null)
{
SET("NAME = #{name}");
}
if (tutor.getEmail() != null)
{
SET("EMAIL = #{email}");
}
WHERE("TUTOR_ID = #{tutorId}");
}
} .toString();
}
}
public interface TutorMapper
{
@UpdateProvider(type = TutorDynaSqlProvider.class,
method = "updateTutor")
int updateTutor(Tutor tutor);
}
public class TutorDynaSqlProvider
{
public String deleteTutor(int tutorId)
{
return new SQL()
{
{
DELETE_FROM("TUTORS");
WHERE("TUTOR_ID = #{tutorId}");
}
} .toString();
}
}
public interface TutorMapper
{
@DeleteProvider(type = TutorDynaSqlProvider.class,
method = "deleteTutor")
int deleteTutor(int tutorId);
}
- 在利用注解配置映射器接口的时候,必须要通过 sqlSessionFactory.getConfiguration().addMapper(IBlogDAO.class);来对给映射器接口注册,如果映射器接口中使用了@ResultMap注解,则由于已经在mybatis-config.xml配置了Mapper,则就不需要再次在代码中添加mapper。
- 当方法有多个参数的时候,为了与SQL语句中的#{}对应,一般可以使用@Param("")来为每个参数命别名,使得该别名与#{}对应。当参数只有一个的时候,不需要别名。
- 在进行更新删除添加的时候,如果传递的是一个实体对象,则SQL可以直接使用实体的属性。
- 映射器接口调用SqlBuilder中的方法,都是将参数转换为Map中的key,可以在SqlBuilder的方法中利用Map来获取传递的参数值,进而进行逻辑操作判断。
- 注解中对于返回多条记录的查询可以直接利用@Results和@Result来配置映射,或者利用@ResultMap来调用SQL配置文件中的ResultMap。