2014-04-21 17:09:55
MyBatis可以利用SQL映射文件来配置,也可以利用Annotation来设置。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}。 |
这些注解都是运用到传统意义上映射器接口中的方法、类或者方法参数中的。
今天主要介绍两种使用注解的方式。
一种是直接在映射器接口中写SQL语句,一种是利用SqlBuilder来创建SQL再由映射器接口来调用
准备前提:
1,配置常规的MyBatis主配置文件,即各种数据源,别名等设置。在利用注解配置SQL的时候,一般不需要在主配置文件中配置Mapper,个别情况下需要配置。
2,数据库表Blog:
1
2
3
4
5
6
7
8
9
|
DROP TABLE IF EXISTS `blog`;
CREATE TABLE `blog` (
`id` int (10) NOT NULL auto_increment,
`title` varchar (200) NOT NULL ,
` date ` varchar (50) NOT NULL ,
`authername` varchar (15) NOT NULL ,
`content` varchar (500) NOT NULL ,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
数据库表User:
1
2
3
4
5
6
7
8
|
DROP TABLE IF EXISTS ` user `;
CREATE TABLE ` user ` (
`id` int (11) NOT NULL auto_increment,
`userName` varchar (50) default NULL ,
`userAge` int (11) default NULL ,
`userAddress` varchar (200) default NULL ,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
3,分别写User和Blog对应的JavaBean即setter和getter实体类。
第一种 映射器接口中写SQL语句
映射器接口注解
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
package com.whut.inter;
import java.util.List;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import com.whut.model.User;
//最基本的注解CRUD public interface IUserDAO {
@Select ( "select *from User" )
public List<User> retrieveAllUsers();
//注意这里只有一个参数,则#{}中的标识符可以任意取
@Select ( "select *from User where id=#{idss}" )
public User retrieveUserById( int id);
@Select ( "select *from User where id=#{id} and userName like #{name}" )
public User retrieveUserByIdAndName( @Param ( "id" ) int id, @Param ( "name" )String names);
@Insert ( "INSERT INTO user(userName,userAge,userAddress) VALUES(#{userName},"
+ "#{userAge},#{userAddress})" )
public void addNewUser(User user);
@Delete ( "delete from user where id=#{id}" )
public void deleteUser( int id);
@Update ( "update user set userName=#{userName},userAddress=#{userAddress}"
+ " where id=#{id}" )
public void updateUser(User user);
} |
测试代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
package com.whut.test;
import java.io.IOException;
import java.io.Reader;
import java.util.List;
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 com.whut.inter.IUserDAO;
import com.whut.model.User;
public class TestUser {
private static SqlSessionFactory sqlSessionFactory;
private static Reader reader;
static {
try {
Reader reader = Resources.getResourceAsReader( "mybatic-config.xml" );
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
// 由于使用了注解,所以在主配置文件没有mapper,需要在代码里显示注册该mapper接口
sqlSessionFactory.getConfiguration().addMapper(IUserDAO. class );
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// testSelectAll();
// testSelectByConditions();
//testAddUser();
//testDeleteUser();
testUpateUser();
}
public static void testSelectAll() {
// sqlSessionFactory.getConfiguration().addMapper(IUserDAO.class);
SqlSession session = sqlSessionFactory.openSession();
try {
IUserDAO userDAO = session.getMapper(IUserDAO. class );
List<User> users = userDAO.retrieveAllUsers();
System.out.println( "用户编号\t" + "姓名\t" + "年龄\t住址" );
for (User u : users) {
System.out.println(u.getId() + "\t" + u.getUserName() + "\t"
+ u.getUserAge() + "\t" + u.getUserAddress());
}
} finally {
session.close();
}
}
public static void testSelectByConditions() {
SqlSession session = sqlSessionFactory.openSession();
try {
IUserDAO userDAO = session.getMapper(IUserDAO. class );
User u = userDAO.retrieveUserByIdAndName( 4 , "%spring%" );
if (u != null ) {
System.out.println( "用户编号\t" + "姓名\t" + "年龄\t住址" );
System.out.println(u.getId() + "\t" + u.getUserName() + "\t"
+ u.getUserAge() + "\t" + u.getUserAddress());
}
} finally {
session.close();
}
}
public static void testAddUser() {
User u = new User();
u.setUserName( "dongtian" );
u.setUserAge( 51 );
u.setUserAddress( "hubeisheng" );
SqlSession session = sqlSessionFactory.openSession();
try {
IUserDAO userDAO = session.getMapper(IUserDAO. class );
userDAO.addNewUser(u);
session.commit();
} finally {
session.close();
}
}
public static void testDeleteUser() {
SqlSession session = sqlSessionFactory.openSession();
try {
IUserDAO userDAO = session.getMapper(IUserDAO. class );
userDAO.deleteUser( 7 );
session.commit();
} finally {
session.close();
}
}
public static void testUpateUser() {
User u = new User();
u.setId( 4 );
u.setUserName( "dongtian" );
u.setUserAge( 51 );
u.setUserAddress( "hubeisheng" );
SqlSession session = sqlSessionFactory.openSession();
try {
IUserDAO userDAO = session.getMapper(IUserDAO. class );
userDAO.updateUser(u);
session.commit();
} finally {
session.close();
}
}
} |
第二种 映射器接口调用SqlBuilder生成的SQL进行执行
映射器接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
package com.whut.inter;
import java.util.List;
import org.apache.ibatis.annotations.CacheNamespace;
import org.apache.ibatis.annotations.DeleteProvider;
import org.apache.ibatis.annotations.InsertProvider;
import org.apache.ibatis.annotations.Options;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.ResultMap;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.SelectProvider;
import org.apache.ibatis.annotations.UpdateProvider;
import org.apache.ibatis.type.JdbcType;
import com.whut.model.Blog;
import com.whut.sqlTool.BlogSqlProvider;
@CacheNamespace (size= 100 )
public interface IBlogDAO {
@SelectProvider (type = BlogSqlProvider. class , method = "getSql" )
@Results (value ={
@Result (id= true , property= "id" ,column= "id" ,javaType=Integer. class ,jdbcType=JdbcType.INTEGER),
@Result (property= "title" ,column= "title" ,javaType=String. class ,jdbcType=JdbcType.VARCHAR),
@Result (property= "date" ,column= "date" ,javaType=String. class ,jdbcType=JdbcType.VARCHAR),
@Result (property= "authername" ,column= "authername" ,javaType=String. class ,jdbcType=JdbcType.VARCHAR),
@Result (property= "content" ,column= "content" ,javaType=String. class ,jdbcType=JdbcType.VARCHAR),
})
public Blog getBlog( @Param ( "id" ) int id);
@SelectProvider (type = BlogSqlProvider. class , method = "getAllSql" )
@Results (value ={
@Result (id= true , property= "id" ,column= "id" ,javaType=Integer. class ,jdbcType=JdbcType.INTEGER),
@Result (property= "title" ,column= "title" ,javaType=String. class ,jdbcType=JdbcType.VARCHAR),
@Result (property= "date" ,column= "date" ,javaType=String. class ,jdbcType=JdbcType.VARCHAR),
@Result (property= "authername" ,column= "authername" ,javaType=String. class ,jdbcType=JdbcType.VARCHAR),
@Result (property= "content" ,column= "content" ,javaType=String. class ,jdbcType=JdbcType.VARCHAR),
})
public List<Blog> getAllBlog();
@SelectProvider (type = BlogSqlProvider. class , method = "getSqlByTitle" )
@ResultMap (value = "sqlBlogsMap" )
//这里调用resultMap,这个是SQL配置文件中的,必须该SQL配置文件与本接口有相同的全限定名
//注意文件中的namespace路径必须是使用@resultMap的类路径
public List<Blog> getBlogByTitle( @Param ( "title" )String title);
@InsertProvider (type = BlogSqlProvider. class , method = "insertSql" )
public void insertBlog(Blog blog);
@UpdateProvider (type = BlogSqlProvider. class , method = "updateSql" )
public void updateBlog(Blog blog);
@DeleteProvider (type = BlogSqlProvider. class , method = "deleteSql" )
@Options (useCache = true , flushCache = false , timeout = 10000 )
public void deleteBlog( int ids);
} |
SQL生成器(利用SqlBuilder生成)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
package com.whut.sqlTool;
import java.util.Map;
import static org.apache.ibatis.jdbc.SqlBuilder.*;
public class BlogSqlProvider {
private final static String TABLE_NAME = "blog" ;
public String getSql(Map<Integer, Object> parameter) {
BEGIN();
//SELECT("id,title,authername,date,content");
SELECT( "*" );
FROM(TABLE_NAME);
//注意这里这种传递参数方式,#{}与map中的key对应,而map中的key又是注解param设置的
WHERE( "id = #{id}" );
return SQL();
}
public String getAllSql() {
BEGIN();
SELECT( "*" );
FROM(TABLE_NAME);
return SQL();
}
public String getSqlByTitle(Map<String, Object> parameter) {
String title = (String) parameter.get( "title" );
BEGIN();
SELECT( "*" );
FROM(TABLE_NAME);
if (title != null )
WHERE( " title like #{title}" );
return SQL();
}
public String insertSql() {
BEGIN();
INSERT_INTO(TABLE_NAME);
VALUES( "title" , "#{title}" );
// VALUES("title", "#{tt.title}");
//这里是传递一个Blog对象的,如果是利用上面tt.方式,则必须利用Param来设置别名
VALUES( "date" , "#{date}" );
VALUES( "authername" , "#{authername}" );
VALUES( "content" , "#{content}" );
return SQL();
}
public String deleteSql() {
BEGIN();
DELETE_FROM(TABLE_NAME);
WHERE( "id = #{id}" );
return SQL();
}
public String updateSql() {
BEGIN();
UPDATE(TABLE_NAME);
SET( "content = #{content}" );
WHERE( "id = #{id}" );
return SQL();
}
} |
注意由于在映射器接口中调用了@ResultMap,该注解内容是SQL配置文件ResultMap的ID,它是允许访问SQL配置文件中的ResultMap,则需要在相应的SQL配置相应ResultMap,然后再在主配置文件加上该SQL配置的Mapper路径。并且该SQL配置文件的namespace必须与使用@ResultMap的映射器接口的全限定相同。Blog.xml如下。
1
2
3
4
5
6
7
8
9
10
11
12
|
<? 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.whut.inter.IBlogDAO" >
< resultMap type = "Blog" id = "sqlBlogsMap" >
< id property = "id" column = "id" />
< result property = "title" column = "title" />
< result property = "authername" column = "authername" />
< result property = "date" column = "date" />
< result property = "content" column = "content" />
</ resultMap >
</ mapper >
|
再在主配置文件mybatis-config.xml加入一句mapper。
1
2
3
|
< mappers >
< mapper resource = "com/whut/model/Blog.xml" />
</ mappers >
|
测试类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
package com.whut.test;
import java.io.IOException;
import java.io.Reader;
import java.util.List;
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 com.whut.inter.IBlogDAO;
import com.whut.model.Blog;
/** * 注意这里是一种利用SqlBuilder以及多种设置来注解使用
* @author zxl
*
*/
public class TestBlog {
private static SqlSessionFactory sqlSessionFactory;
private static Reader reader;
static {
try {
Reader reader = Resources.getResourceAsReader( "mybatic-config.xml" );
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
// 由于使用了注解,所以在主配置文件没有mapper,需要在代码里显示注册该mapper接口
//sqlSessionFactory.getConfiguration().addMapper(IBlogDAO.class);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
//testOneBlog();
//testAllBlog();
//testBlogByTitle();
//testAddBlog();
//testDeleteBlog();
testUpdateBlog();
}
public static void testOneBlog()
{
SqlSession session=sqlSessionFactory.openSession();
try {
IBlogDAO dao=session.getMapper(IBlogDAO. class );
Blog blog=dao.getBlog( 2 );
System.out.println(blog.getId()+ "\t" +blog.getAuthername()+ "\t" +blog.getTitle());
} finally {
session.close();
}
}
public static void testAllBlog()
{
SqlSession session=sqlSessionFactory.openSession();
try {
IBlogDAO dao=session.getMapper(IBlogDAO. class );
List<Blog> blogs=dao.getAllBlog();
System.out.println( "编号\t作者\t标题" );
for (Blog blog:blogs)
System.out.println(blog.getId()+ "\t" +blog.getAuthername()+ "\t" +blog.getTitle());
} finally {
session.close();
}
}
public static void testBlogByTitle()
{
SqlSession session=sqlSessionFactory.openSession();
try {
IBlogDAO dao=session.getMapper(IBlogDAO. class );
List<Blog> blogs=dao.getBlogByTitle( "%word%" );
System.out.println( "编号\t作者\t标题" );
for (Blog blog:blogs)
System.out.println(blog.getId()+ "\t" +blog.getAuthername()+ "\t" +blog.getTitle());
} finally {
session.close();
}
}
public static void testAddBlog()
{
SqlSession session=sqlSessionFactory.openSession();
Blog blog= new Blog();
blog.setTitle( "chuntian" );
blog.setAuthername( "xiaohua" );
blog.setDate( "2013/12/25" );
blog.setContent( "bushuangyayya" );
try {
IBlogDAO dao=session.getMapper(IBlogDAO. class );
dao.insertBlog(blog);
session.commit();
} finally {
session.close();
}
}
public static void testDeleteBlog()
{
SqlSession session=sqlSessionFactory.openSession();
try {
IBlogDAO dao=session.getMapper(IBlogDAO. class );
dao.deleteBlog( 5 );
session.commit();
} finally {
session.close();
}
}
public static void testUpdateBlog()
{
SqlSession session=sqlSessionFactory.openSession();
Blog blog= new Blog();
blog.setId( 6 );
blog.setTitle( "daxuexiaoyuan" );
blog.setAuthername( "xiaohua" );
blog.setDate( "2013/2/25" );
blog.setContent( "冷死了" );
try {
IBlogDAO dao=session.getMapper(IBlogDAO. class );
dao.updateBlog(blog);
session.commit();
} finally {
session.close();
}
}
} |
注意事项:
1) 在利用注解配置映射器接口的时候,必须要通过
sqlSessionFactory.getConfiguration().addMapper(IBlogDAO.class);来对给映射器接口注册,如果映射器接口中使用了@ResultMap注解,则由于已经在mybatis-config.xml配置了Mapper,则就不需要再次在代码中添加mapper。
2)当方法有多个参数的时候,为了与SQL语句中的#{}对应,一般可以使用@Param("")来为每个参数命别名,使得该别名与#{}对应。当参数只有一个的时候,不需要别名。
3 在进行更新删除添加的时候,如果传递的是一个实体对象,则SQL可以直接使用实体的属性。
4)映射器接口调用SqlBuilder中的方法,都是将参数转换为Map中的key,可以在SqlBuilder的方法中利用Map来获取传递的参数值,进而进行逻辑操作判断。
5)注解中对于返回多条记录的查询可以直接利用@Results和@Result来配置映射,或者利用@ResultMap来调用SQL配置文件中的ResultMap。
本文出自 “在云端的追梦” 博客,请务必保留此出处http://computerdragon.blog.51cto.com/6235984/1399742