文章目錄
回顧:
MyBatis框架快速入門(一),搭建MyBatis開發環境
MyBatis框架快速入門(二),使用映射器接口代理對象的方式實現單表的增刪改查
MyBatis框架進階(一),動態Sql,多表關聯查詢與延遲加載策略
之前的CRUD操作是基於 Mybaits 的映射文件來實現的,簡單的CRUD使用配置映射文件的方式實現編碼較繁瑣,這時可以考慮使用Mybatis的註解開發,基於註解的映射方式,實現CRUD,只是將配置映射文件的過程替換了,只要將sql語句直接寫入註解的括號中即可,其他配置編碼與之前的方式是一樣的。
這裏實現也只要編寫接口,而不用寫實現類。(有接口,沒有實現類,生成代理對象,由代理對象完成功能)
Mybatis註解開發-實現單表的增刪改查
- user表的實體類
public class User {
private Integer id;
private String username;
private String password;
private String email;
private Date birthday;
...
...
}
- 映射器接口UserMapper
public interface UserMapper {
//查詢所有用戶
@Select("select * from t_user")
List<User> queryAllUser();
//根據id查詢用戶信息
@Select("select * from t_user where id=#{id}")
User selectUserByid(int id);
//增加用戶
@Insert("insert into t_user (id,username,password,email,birthday) values (#{id},#{username},#{password},#{email},#{birthday})")
@SelectKey(keyProperty = "id",resultType = Integer.class,before = false,statement ="select last_insert_id()")
/**
* @SelectKeyz註解:
* statement="要執行的SQL語句"
* keyProperty="將上述SQL語句查詢的結果賦值給入參的指定屬性" 這裏是賦值給user的id
* before="SelectKey中的SQL語句是否先執行" oracle爲true
* resultType="上述SQL語句查詢出的數據需要轉換的數據類型(數據類型和被賦值的屬性類型必須一致)"
*
*/
int insertUser(User user);
//更新指定用戶信息
@Update(" update t_user set password=#{password},email=#{email} where id=#{id}")
void updateUser(User user);
//根據id刪除指定用戶
@Delete("delete from t_user where id=#{id}")
void deleteUser(int id);
//根據用戶名模糊查詢
@Select("select * from t_user where username like #{username}")
List<User> selectUserByUserName(String username);
//根據用戶名模糊查詢
@Select("select * from t_user where username like '%${value}%'")
List<User> selectUserByUserName2(String username);
@Select("select count(*) from t_user")
//查詢總記錄數
int getTotalCount();
}
- 這裏測試增加操作 測試
@SelectKey
註解的作用
- 使用mysql數據庫
@Test
public void insertUserTest() throws IOException {
User user = new User();
user.setUsername("張三三");
user.setPassword("3");
user.setEmail("[email protected]");
user.setBirthday( new Date());
System.out.println("插入數據前"+user);
//User{id=null, username='張三三', password='3', email='[email protected]', birthday=Sat Apr 04 14:50:17 CST 2020}
mapper.insertUser(user);
sqlSession.commit();
/*使用的是mysql數據庫
當插入數據後,要在界面顯示該數據時,應主鍵(id)是自增的,沒有賦值插入,
所以這裏插入數據後 輸出的id就爲null,可以通過@SelectKey來查詢id的值,並返回顯示。
*/
System.out.println("插入數據後"+user);
//User{id=24, username='張三三', password='3', email='[email protected]', birthday=Sat Apr 04 14:50:17 CST 2020}
}
- 使用oracle數據庫,序列實現自增,使用
@SelectKey
註解可在插入數據前賦值給入參的指定屬性(如id),即可實現id自增。(@SelectKey
註解更多運用於此)
JavaBean中屬性名和字段名不一致的情況解決方案
- user表的實體類
public class User {
private Integer uid;
private String uname;
private String upassword;
private String uemail;
private Date ubirthday;
...
....
}
- 映射器接口UserMapper
//查詢所有用戶
@Select("select * from t_user")
//@Results:相當於映射配置文件裏的resultMap標籤
//@Result:相當於映射配置文件裏的result標籤,@Result和@Results配合使用,封裝結果集。
@Results(value = {
@Result(property ="uid",column ="id",id = true), //是否爲主鍵
@Result(property ="uname" ,column ="username" ),
@Result(property ="upassword",column ="password" ),
@Result(property ="uemail" ,column ="email" ),
@Result(property ="ubirthday" ,column ="birthday")
})
List<AliasUser> selectAllAliasUser();
參考映射配置文件
Mybatis註解開發-多表關聯查詢並實現延遲加載
user表
account表
一對多(多對多)關聯查詢:查詢用戶信息,以及每個用戶擁有的所有帳號信息
- user表和account表的實體類
public class User {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
private List<Account> accountList;
....
...
}
public class Account {
private Integer id;
private Integer uid;
private Double money;
private User user;
..
...
}
- 映射器接口UserMapper
public interface UserMapper {
//一對多(多對多)關聯查詢:查詢用戶信息,以及每個用戶擁有的所有帳號信息
@Select("select * from user")
@Results({
@Result(
javaType = List.class,//數據類型 注意,這裏是List.class,而不是Account.class 。 ①測試過 javaType不寫也可
many = @Many( //@Many用於封裝JavaBean中某一屬性關聯的集合,用於一對多(多對多)情形
select = "com.mycode.mapper.AccountMapper.selectAccountById", //調用外部功能查詢
fetchType = FetchType.LAZY //懶加載
),
column ="id",//調用功能時傳遞的參數從哪個字段裏取 注意這裏映射後 需要寫 @Result(property ="id",column ="id") 否則查詢得到的User的id爲null
property ="accountList"//查詢的結果集封裝到User中哪個屬性
),
@Result(property ="id",column ="id",id = true) //上面調用了id,這裏需要再給id賦值,否則爲null
})
List<User> queryAllUser();
}
- 編寫映射器接口UserMapper所調用的外部功能,需要提供 查詢關聯的賬戶信息功能
public interface AccountMapper {
//根據用戶id查詢賬戶
@Select("select * from account where uid=#{id}")
List<Account> selectAccountById(int id);
}
- 測試1 延遲加載效果
@Test
public void testQueryAllUser(){
List<User> userList = userMapper.queryAllUser();
for (User user : userList) {
//這裏只獲取用戶信息,只執行查詢用戶信息的SQL語句
System.out.println(user.getUsername() +", " + user.getSex());
}
}
測試中只使用了用戶信息,所以只會查詢用戶信息,執行查詢用戶的SQL語句
- 測試2
@Test
public void testQueryAllUser(){
List<User> userList = userMapper.queryAllUser();
for (User user : userList) {
//這裏只獲取用戶信息,只執行查詢用戶信息的SQL語句
System.out.println(user.getUsername() +", " + user.getSex());
//當使用用戶關聯帳號信息時,會執行查詢帳號信息的SQL語句,只查詢用戶id爲32的賬號信息(即按需查詢)
if (user.getId() == 32) {
System.out.println(user.getAccountList());
}
}
}
測試中查詢了用戶信息,並判斷了用戶id爲32的,查詢其賬戶信息。(這裏其他用戶的賬戶信息並不會查詢)
回顧:MyBatis框架進階(一),動態Sql,多表關聯查詢與延遲加載策略
一對一(多對一)關聯查詢:查詢賬戶信息及關聯的用戶信息
- user表和account表的實體類
public class Account {
private Integer id;
private Integer uid;
private Double money;
private User user;
..
...
}
public class User {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
private List<Account> accountList;
....
...
}
- 映射器接口AccountMapper
public interface AccountMapper {
//一對一(多對一)關聯查詢:查詢賬戶信息及關聯的用戶信息
@Select("select * from account")
@Results({
@Result(property = "id",column = "id",id = true),
@Result(property = "uid",column = "uid"),
@Result(property = "money",column = "money"),
@Result(
javaType = User.class,//關聯的JavaBean的字節碼
one=@One(
select ="com.mycode.mapper.UserMapper.selectUserByid"//調用哪個功能,查詢得到關聯的JavaBean對象
fetchType = FetchType.LAZY //懶加載
),
column = "uid",//調用功能時傳遞的參數從哪個字段裏取
property = "user"//封裝哪個屬性關聯的JavaBean
)
})
List<Account> queryAllAccount()
}
- 編寫映射器接口AccountMapper 所調用的外部功能,需要提供 查詢關聯用戶信息功能
public interface UserMapper {
//根據賬號uid查詢用戶信息
@Select("select * from user where id=#{uid}")
User selectUserByid(int id);
}
- 測試1
@Test
public void testQueryAllAccount(){
List<Account> accounts = accountMapper.queryAllAccount();
for (Account account : accounts) {
//只使用了帳號信息,只執行查詢帳號的SQL語句
System.out.println(account.getId() +", " +account.getMoney());
}
}
- 測試2
@Test
public void testQueryAllAccount(){
List<Account> accounts = accountMapper.queryAllAccount();
for (Account account : accounts) {
//只使用了帳號信息,只執行查詢帳號的SQL語句
System.out.println(account.getId() +", " +account.getMoney());
//當需要使用用戶信息時,纔會執行查詢用戶的SQL語句
System.out.println(account.getUser());
}
}