這幾年來註解開發越來越流行,Mybatis 也可以使用註解開發方式,這樣我們就可以減少編寫 Mapper 對映 檔案了。本次我們先圍繞一些基本的 CRUD 來學習,再學習複雜對映關係及延遲載入。
3.1 mybatis 的常用註解說明
@Insert
:
實現新增
@Update
:
實現更新
@Delete
:
實現刪除
@Select
:
實現查詢
@Result
:
實現結果集封裝
@Results
:
可以與
@Result
一起使用
,
封裝多個結果集
@ResultMap
:
實現引用
@Results
定義的封裝
@One
:
實現一對一結果集封裝
@Many
:
實現一對多結果集封裝
@SelectProvider
:
實現動態
SQL
對映
@CacheNamespace
:
實現註解二級快取的使用
3.2 使用 Mybatis 註解實現基本 CRUD
單表的 CRUD 操作是最基本的操作,前面我們的學習都是基於 Mybaits 的對映檔案來實現的。
3.2.1 編寫實體類
package
com。itheima。domain
;
import
java。io。Serializable
;
import
java。util。Date
;
/**
* @author 黑馬程式設計師
* @Company http://www。ithiema。com
*/
public
class
User
implements
Serializable
{
private
Integer
id
;
private
String
username
;
private
String
address
;
private
String
sex
;
private
Date
birthday
;
public
Integer
getId
()
{
return
id
;
}
public
void
setId
(
Integer
id
)
{
this
。
id
=
id
;
}
public
String
getUsername
()
{
return
username
;
}
public
void
setUsername
(
String
username
)
{
this
。
username
=
username
;
}
public
String
getAddress
()
{
return
address
;
}
public
void
setAddress
(
String
address
)
{
this
。
address
=
address
;
}
public
String
getSex
()
{
return
sex
;
}
public
void
setSex
(
String
sex
)
{
this
。
sex
=
sex
;
}
public
Date
getBirthday
()
{
return
birthday
;
}
public
void
setBirthday
(
Date
birthday
)
{
this
。
birthday
=
birthday
;
}
@Override
public
String
toString
()
{
return
“User{”
+
“id=”
+
id
+
“, username=‘”
+
username
+
’\‘’
+
“, address=‘”
+
address
+
’\‘’
+
“, sex=‘”
+
sex
+
’\‘’
+
“, birthday=”
+
birthday
+
‘}’
;
}
}
注意: 此處我們故意和資料庫表的列名不一致。
3.2.2 使用註解方式開發持久層介面
3.2.2 使用註解方式開發持久層介面
完整的DAO類
public
interface
IUserDao
{
/**
* 查詢所有使用者
* @return
*/
@Select
(
“select * from user”
)
List
<
User
>
findAll
();
/**
* 儲存使用者
* @param user
*/
@Insert
(
“insert into user(username,address,sex,birthday)values(#{username},#{address},#{sex},#{birthday})”
)
void
saveUser
(
User
user
);
/**
* 更新使用者
* @param user
*/
@Update
(
“update user set username=#{username},sex=#{sex},birthday=#{birthday},address=#{address} where id=#{id}”
)
void
updateUser
(
User
user
);
/**
* 刪除使用者
* @param userId
*/
@Delete
(
“delete from user where id=#{id} ”
)
void
deleteUser
(
Integer
userId
);
/**
* 根據id查詢使用者
* @param userId
* @return
*/
@Select
(
“select * from user where id=#{id} ”
)
User
findById
(
Integer
userId
);
/**
* 根據使用者名稱稱模糊查詢
* @param username
* @return
*/
// @Select(“select * from user where username like #{username} ”)
@Select
(
“select * from user where username like ‘%${value}%’ ”
)
List
<
User
>
findUserByName
(
String
username
);
/**
* 查詢總使用者數量
* @return
*/
@Select
(
“select count(*) from user ”
)
int
findTotalUser
();
}
3.2.3 編寫 SqlMapConfig 配置檔案
<?xml version=“1。0” encoding=“UTF-8”?>
<!DOCTYPE configuration
PUBLIC “-//mybatis。org//DTD Config 3。0//EN”
“http://mybatis。org/dtd/mybatis-3-config。dtd”>
<!—— 引入外部配置檔案——>
resource= “jdbcConfig。properties” >
<!——配置別名——>
name= “com。itheima。domain” >
<!—— 配置環境——>
default= “mysql” > id= “mysql” > type= “JDBC” > type= “POOLED” > name= “driver” value= “${jdbc。driver}” > name= “url” value= “${jdbc。url}” > name= “username” value= “${jdbc。username}” > name= “password” value= “${jdbc。password}” >
<!—— 指定帶有註解的dao介面所在位置 ——>
class= “com。itheima。dao。IUserDao” >
3.2.4 編寫測試方法
@Test
public
void
testSave
(){
User
user
=
new
User
();
user
。
setUsername
(
“mybatis annotation”
);
user
。
setAddress
(
“北京市昌平區”
);
userDao
。
saveUser
(
user
);
}
@Test
public
void
testUpdate
(){
User
user
=
new
User
();
user
。
setId
(
57
);
user
。
setUsername
(
“mybatis annotation update”
);
user
。
setAddress
(
“北京市海淀區”
);
user
。
setSex
(
“男”
);
user
。
setBirthday
(
new
Date
());
userDao
。
updateUser
(
user
);
}
@Test
public
void
testDelete
(){
userDao
。
deleteUser
(
51
);
}
@Test
public
void
testFindOne
(){
User
user
=
userDao
。
findById
(
57
);
System
。
out
。
println
(
user
);
}
@Test
public
void
testFindByName
(){
// List
List
<
User
>
users
=
userDao
。
findUserByName
(
“mybatis”
);
for
(
User
user
:
users
){
System
。
out
。
println
(
user
);
}
}
@Test
public
void
testFindTotal
(){
int
total
=
userDao
。
findTotalUser
();
System
。
out
。
println
(
total
);
}
3.3 使用註解實現複雜關係對映開發
實現複雜關係對映之前我們可以在對映檔案中透過配置
@Results 註解,@Result 註解,@One 註解,@Many 註解。
3.3.1 複雜關係對映的註解說明
@
Results
註解
代替的是標籤
<
resultMap
>
該註解中可以使用單個
@
Result
註解
,
也可以使用
@
Result
集合
@
Results
(
{
@
Result
(),@
Result
()
}
)
或
@
Results
(@
Result
())
@
Resutl
註解
代替了
<
id
>
標籤和
<
result
>
標籤
@
Result
中
屬性介紹
:
id
是否是主鍵欄位
column
資料庫的列名
property
需要裝配的屬性名
one
需要使用的
@
One
註解
(@
Result
(
one
=
@
One
)()))
many
需要使用的
@
Many
註解
(@
Result
(
many
=
@
many
)()))
@
One
註解
(
一對一
)
代替了
<
assocation
>
標籤
,
是多表查詢的關鍵
,
在註解中用來指定子查詢返回單一物件
。
@
One
註解屬性介紹
:
select
指定用來多表查詢的
sqlmapper
fetchType
會覆蓋全域性的配置引數
lazyLoadingEnabled
。。
使用格式
:
@
Result
(
column
=
“ ”
,
property
=
“”
,
one
=
@
One
(
select
=
“”
))
@
Many
註解
(
多對一
)
代替了
<
Collection
>
標籤
,
是是多表查詢的關鍵
,
在註解中用來指定子查詢返回物件集合
。
注意
:
聚集元素用來處理
“
一對多
”
的關係
。
需要指定對映的
Java
實體類的屬性
,
屬性的
javaType
(
一般為
ArrayList
)
但是註解中可以不定義
;
使用格式
:
@
Result
(
property
=
“”
,
column
=
“”
,
many
=
@
Many
(
select
=
“”
))
3.3.2 使用註解實現一對一複雜關係對映及延遲載入
需求: 載入賬戶資訊時並且載入該賬戶的使用者資訊,根據情況可實現延遲載入。(註解方式實現)
3.3.2.1 新增 User 實體類及 Account 實體類
public
class
User
implements
Serializable
{
private
Integer
userId
;
private
String
userName
;
private
String
userAddress
;
private
String
userSex
;
private
Date
userBirthday
;
//一對多關係對映:一個使用者對應多個賬戶
private
List
<
Account
>
accounts
;
public
List
<
Account
>
getAccounts
()
{
return
accounts
;
}
public
void
setAccounts
(
List
<
Account
>
accounts
)
{
this
。
accounts
=
accounts
;
}
public
Integer
getUserId
()
{
return
userId
;
}
public
void
setUserId
(
Integer
userId
)
{
this
。
userId
=
userId
;
}
public
String
getUserName
()
{
return
userName
;
}
public
void
setUserName
(
String
userName
)
{
this
。
userName
=
userName
;
}
public
String
getUserAddress
()
{
return
userAddress
;
}
public
void
setUserAddress
(
String
userAddress
)
{
this
。
userAddress
=
userAddress
;
}
public
String
getUserSex
()
{
return
userSex
;
}
public
void
setUserSex
(
String
userSex
)
{
this
。
userSex
=
userSex
;
}
public
Date
getUserBirthday
()
{
return
userBirthday
;
}
public
void
setUserBirthday
(
Date
userBirthday
)
{
this
。
userBirthday
=
userBirthday
;
}
@Override
public
String
toString
()
{
return
“User{”
+
“userId=”
+
userId
+
“, userName=‘”
+
userName
+
’\‘’
+
“, userAddress=‘”
+
userAddress
+
’\‘’
+
“, userSex=‘”
+
userSex
+
’\‘’
+
“, userBirthday=”
+
userBirthday
+
‘}’
;
}
}
public
class
Account
implements
Serializable
{
private
Integer
id
;
private
Integer
uid
;
private
Double
money
;
//多對一(mybatis中稱之為一對一)的對映:一個賬戶只能屬於一個使用者
private
User
user
;
public
User
getUser
()
{
return
user
;
}
public
void
setUser
(
User
user
)
{
this
。
user
=
user
;
}
public
Integer
getId
()
{
return
id
;
}
public
void
setId
(
Integer
id
)
{
this
。
id
=
id
;
}
public
Integer
getUid
()
{
return
uid
;
}
public
void
setUid
(
Integer
uid
)
{
this
。
uid
=
uid
;
}
public
Double
getMoney
()
{
return
money
;
}
public
void
setMoney
(
Double
money
)
{
this
。
money
=
money
;
}
@Override
public
String
toString
()
{
return
“Account{”
+
“id=”
+
id
+
“, uid=”
+
uid
+
“, money=”
+
money
+
‘}’
;
}
}
3.3.2.2 新增賬戶的持久層介面並使用註解配置
public
interface
IAccountDao
{
/**
* 查詢所有賬戶,並且獲取每個賬戶所屬的使用者資訊
* @return
*/
@Select
(
“select * from account”
)
@Results
(
id
=
“accountMap”
,
value
=
{
@Result
(
id
=
true
,
column
=
“id”
,
property
=
“id”
),
@Result
(
column
=
“uid”
,
property
=
“uid”
),
@Result
(
column
=
“money”
,
property
=
“money”
),
@Result
(
property
=
“user”
,
column
=
“uid”
,
one
=
@One
(
select
=
“com。itheima。dao。IUserDao。findById”
,
fetchType
=
FetchType
。
EAGER
))
})
List
<
Account
>
findAll
();
/**
* 根據使用者id查詢賬戶資訊
* @param userId
* @return
*/
@Select
(
“select * from account where uid = #{userId}”
)
List
<
Account
>
findAccountByUid
(
Integer
userId
);
}
3.3.2.3 新增使用者的持久層介面並使用註解配置
@CacheNamespace
(
blocking
=
true
)
public
interface
IUserDao
{
/**
* 查詢所有使用者
* @return
*/
@Select
(
“select * from user”
)
@Results
(
id
=
“userMap”
,
value
={
@Result
(
id
=
true
,
column
=
“id”
,
property
=
“userId”
),
@Result
(
column
=
“username”
,
property
=
“userName”
),
@Result
(
column
=
“address”
,
property
=
“userAddress”
),
@Result
(
column
=
“sex”
,
property
=
“userSex”
),
@Result
(
column
=
“birthday”
,
property
=
“userBirthday”
),
@Result
(
property
=
“accounts”
,
column
=
“id”
,
many
=
@Many
(
select
=
“com。itheima。dao。IAccountDao。findAccountByUid”
,
fetchType
=
FetchType
。
LAZY
))
})
List
<
User
>
findAll
();
/**
* 根據id查詢使用者
* @param userId
* @return
*/
@Select
(
“select * from user where id=#{id} ”
)
@ResultMap
(
“userMap”
)
User
findById
(
Integer
userId
);
/**
* 根據使用者名稱稱模糊查詢
* @param username
* @return
*/
@Select
(
“select * from user where username like #{username} ”
)
@ResultMap
(
“userMap”
)
List
<
User
>
findUserByName
(
String
username
);
}
3.3.2.4 測試一對一關聯及延遲載入
@Test
public
void
testFindAll
(){
List
<
Account
>
accounts
=
accountDao
。
findAll
();
/*
for(Account account : accounts){
System。out。println(“——每個賬戶的資訊——-”);
System。out。println(account);
System。out。println(account。getUser());
}
*/
}
3.3.3 使用註解實現一對多複雜關係對映
需求: 查詢使用者資訊時,也要查詢他的賬戶列表。使用註解方式實現。 分析: 一個使用者具有多個賬戶資訊,所以形成了使用者(User)與賬戶(Account)之間的一對多關係。
3.3.3.1 User 實體類加入 List<Account>
//一對多關係對映:一個使用者對應多個賬戶
private
List
<
Account
>
accounts
;
public
List
<
Account
>
getAccounts
()
{
return
accounts
;
}
public
void
setAccounts
(
List
<
Account
>
accounts
)
{
this
。
accounts
=
accounts
;
}
3.3.3.2 編寫使用者的持久層介面並使用註解配置
@CacheNamespace
(
blocking
=
true
)
public
interface
IUserDao
{
/**
* 查詢所有使用者
* @return
*/
@Select
(
“select * from user”
)
@Results
(
id
=
“userMap”
,
value
={
@Result
(
id
=
true
,
column
=
“id”
,
property
=
“userId”
),
@Result
(
column
=
“username”
,
property
=
“userName”
),
@Result
(
column
=
“address”
,
property
=
“userAddress”
),
@Result
(
column
=
“sex”
,
property
=
“userSex”
),
@Result
(
column
=
“birthday”
,
property
=
“userBirthday”
),
@Result
(
property
=
“accounts”
,
column
=
“id”
,
many
=
@Many
(
select
=
“com。itheima。dao。IAccountDao。findAccountByUid”
,
fetchType
=
FetchType
。
LAZY
))
})
List
<
User
>
findAll
();
/**
* 根據id查詢使用者
* @param userId
* @return
*/
@Select
(
“select * from user where id=#{id} ”
)
@ResultMap
(
“userMap”
)
User
findById
(
Integer
userId
);
/**
* 根據使用者名稱稱模糊查詢
* @param username
* @return
*/
@Select
(
“select * from user where username like #{username} ”
)
@ResultMap
(
“userMap”
)
List
<
User
>
findUserByName
(
String
username
);
}
@Many
:
相當於
<
collection
>
的配置
select
屬性
:
代表將要執行的
sql
語句
fetchType
屬性
:
代表載入方式
,
一般如果要延遲載入都設定為
LAZY
的值
3.3.3.3 編寫賬戶的持久層介面並使用註解配置
/**
* 根據使用者id查詢賬戶資訊
* @param userId
* @return
*/
@Select
(
“select * from account where uid = #{userId}”
)
List
<
Account
>
findAccountByUid
(
Integer
userId
);
3.3.3.4 新增測試方法
/**
* 測試查詢所有 */
@Test
public
void
testFindAll
()
{
List
<
User
>
users
=
userDao
。
findAll
();
//
for
(
User
user
:
users
)
{
System
。
out
。
println
(
“——-每個使用者的內容——-”
);
System
。
out
。
println
(
user
);
//
System
。
out
。
println
(
user
。
getAccounts
());
// }
}
3.4 mybatis 基於註解的二級快取
3.4.1 在 SqlMapConfig 中開啟二級快取支援
<!—— 配置二級快取 ——>
<!—— 開啟二級快取的支援 ——>
name= “cacheEnabled” value= “true” /> 3.4.2 在持久層介面中使用註解配置二級快取