
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