MyBatis--註解式開發
MyBatis--註解式開發
MyBatis的註解,主要是用於替換對映檔案。而對映檔案中無非存放著增刪改查的sql對映標籤。所以,MyBatis註解,就是替換對映檔案中的sql標籤。
常用註解說明:
註解 | 說明 |
---|---|
@Insert | 實現新增 |
@Update | 實現更新 |
@Delete | 實現刪除 |
@Select | 實現查詢 |
@Result | 實現結果集封裝 |
@Results | 可以與@Result 一起使用,封裝多個結果集 |
@ResultMap | 實現引用@Results 定義的封裝 |
@One | 實現一對一結果集封裝 |
@Many | 實現一對多結果集封裝 |
@SelectProvider | 實現動態 SQL 對映 |
@CacheNamespace | 實現註解二級快取的使用 |
一、基本的CRUD
1.@Insert
其value屬性用於指定要執行的insert語句。
2.@SelectKey
用於替換xml中的<selectKey/>
標籤,用於返回新插入資料的id值。
@SelectKey(statement="select @@identity",resultType=int.class,keyProperty="id",before=false
複製程式碼
- statement:獲取新插入記錄主鍵值得sql語句
- keyProperty:獲取的該主鍵值返回後初始化物件的那個屬性
- resultType:返回值型別
- before:指定主鍵的生成相對於insert語句的執行先後順序,該屬性不能省略
3.@Delete
其value屬性用於指定要執行的delete語句。
4.@Update
其value屬性用於指定要執行的update語句。
5.@Select
其value屬性用於指定要執行的select語句。
程式舉例:
SqlMapConfig.xml:
<?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">
<configuration>
<!-- 引入外部配置檔案-->
<properties resource="jdbcConfig.properties"></properties>
<!--配置別名-->
<typeAliases>
<package name="com.hcx.domain"></package>
</typeAliases>
<!-- 配置環境-->
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</dataSource>
</environment>
</environments>
<!-- 指定帶有註解的dao介面所在位置 -->
<mappers>
<mapper class="com.hcx.dao.StudentDao"></mapper>
</mappers>
</configuration>
複製程式碼
1.修改dao介面:
public interface IStudentDao {
@Insert(value={"insert into student(name,age,score) values(#{name},#{age},#{score})"})
void insertStudent(Student student);
@Insert("insert into student(name,#{score})")
@SelectKey(statement="select @@identity",before=false)
void insertStudentCacheId(Student student);
@Delete(value="delete from student where id=#{id}")
void deleteStudentById(int id);
@Update("update student set name=#{name},age=#{age},score=#{score} where id=#{id}")
void updateStudent(Student student);
@Select("select * from student")
List<Student> selectAllStudents();
@Select("select * from student where id=#{id}")
Student selectStudentById(int id);
@Select("select * from student where name like '%' #{name} '%'")
List<Student> selectStudentsByName(String name);
}
複製程式碼
2.刪除對映檔案
3.修改主配置檔案
由於沒有了對映檔案,所以主配置檔案中不能使用<mapper/>
註冊mapper的位置了。需要使用<package/>
標籤
<!-- 註冊對映檔案 -->
<mappers>
<package name="com.hcx.dao"/>
</mappers>
複製程式碼
注意:使用了註解之後,不管主配置檔案(SqlMapConfig.xml)有沒有引用對映檔案,都不能存在對映檔案。可以刪除或者放在其他目錄下。
二、實現複雜關係對映
1.@Result
當實體屬性和資料庫欄位名稱不一致時,使用@Result
註解宣告對映關係
@Results(id = "studentMap",value={
@Result(id=true,column = "id",property = "studentId"),@Result(column = "name",property = "studentName"),@Result(column = "age",property = "studentAge"),@Result(column = "score",property = "studentScore"),})
複製程式碼
id
:唯一標識這段對映,之後可以直接引用,無需重複編寫
id=true
:標識為主鍵欄位
column
:資料庫欄位名
property
:實體屬性名
2.@ResultMap 引用定義好的ResultMap
Student:
@Data
@ToString
public class Student implements Serializable{
private Integer studentId;
private String studentName;
private int studentAge;
private double studentScore;
}
複製程式碼
StudentDao:
public interface StudentDao {
@Select("select * from student")
@Results(id = "studentMap",value={
@Result(id=true,@Result(column = "name",@Result(column = "age",@Result(column = "score",})
List<Student> findAll();
@Select("select * from student where id=#{id}")
@ResultMap(value = {"studentMap"})
Student findById(Integer id);
@Select("select * from student where name like #{name}")
@ResultMap(value = {"studentMap"})
List<Student> findStudentByName(String name);
}
複製程式碼
AnnotationCrudTest:
public class AnnotationCrudTest {
private InputStream in;
private SqlSessionFactory factory;
private SqlSession session;
private StudentDao studentDao;
@Before
public void init()throws Exception{
in = Resources.getResourceAsStream("SqlMapConfig.xml");
factory = new SqlSessionFactoryBuilder().build(in);
session = factory.openSession();
studentDao = session.getMapper(StudentDao.class);
}
@After
public void destroy()throws Exception{
session.commit();
session.close();
in.close();
}
@Test
public void testFindAll(){
List<Student> students = studentDao.findAll();
for(Student student : students){
System.out.println(student);
}
}
@Test
public void testFindById(){
Student student = studentDao.findById(1);
System.out.println(student);
}
@Test
public void testFindByName(){
List<Student> students = studentDao.findStudentByName("%小紅%");
for(Student student : students){
System.out.println(student);
}
}
}
複製程式碼
三、實現多表複雜查詢
1.一對一
Account:
@Data
@ToString
public class Account {
private Integer id;
private Integer studentId;
private Double money;
//多對一:一個賬戶只能屬於一個學生
private Student student;
}
複製程式碼
AccountDao:
public interface AccountDao {
/**
* 查詢所有賬戶並獲取每個賬戶所屬使用者資訊
* @return
*/
@Select("select * from account")
@Results(id = "accountMap",value = {
@Result(id = true,property = "id"),@Result(column = "studentId",@Result(column = "money",property = "money"),@Result(property = "student",column = "studentId",one = @One(select = "com.hcx.dao.StudentDao.findById",fetchType = FetchType.EAGER))
})
List<Account> findAll();
}
複製程式碼
StudentDao:
public interface StudentDao {
@Select("select * from student")
@Results(id = "studentMap",})
List<Student> findAll();
@Select("select * from student where id=#{id}")
@ResultMap(value = {"studentMap"})
Student findById(Integer id);
@Select("select * from student where name like #{name}")
@ResultMap(value = {"studentMap"})
List<Student> findStudentByName(String name);
}
複製程式碼
AccountTest:
@Test
public void testFindAll(){
List<Account> accounts = accountDao.findAll();
for(Account account : accounts){
System.out.println(account);
// System.out.println(account.getStudent());
}
}
複製程式碼
注意:通常對一選擇立即載入,對多選擇延遲載入
2.一對多
Student:
@Data
@ToString
public class Student implements Serializable{
private Integer studentId;
private String studentName;
private int studentAge;
private double studentScore;
//一對多,一個使用者對應多個賬戶
private List<Account> accounts;
}
複製程式碼
StudentDao:
public interface StudentDao {
@Select("select * from student")
@Results(id = "studentMap",@Result(property = "accounts",many = @Many(select = "com.hcx.dao.AccountDao.findAccountByStudentId",fetchType = FetchType.LAZY))
})
List<Student> findAll();
@Select("select * from student where id=#{id}")
@ResultMap(value = {"studentMap"})
Student findById(Integer id);
@Select("select * from student where name like #{name}")
@ResultMap(value = {"studentMap"})
List<Student> findStudentByName(String name);
}
複製程式碼
AccountDao:
public interface AccountDao {
/**
* 查詢所有賬戶並獲取每個賬戶所屬使用者資訊
* @return
*/
@Select("select * from account")
@Results(id = "accountMap",fetchType = FetchType.EAGER))
})
List<Account> findAll();
/**
* 根據學生id查詢學生資訊
* @param studentId
* @return
*/
@Select("select * from account where studentId=#{studentId}")
List<Account> findAccountByStudentId(Integer studentId);
}
複製程式碼
Test:
@Test
public void testFindAll(){
List<Student> students = studentDao.findAll();
for(Student student : students){
System.out.println(student);
}
}
複製程式碼
四、實現二級快取
一級快取:預設就開啟:
@Test
public void testFindById(){
Student student = studentDao.findById(1);
System.out.println(student);
Student student1 = studentDao.findById(1);
System.out.println(student1);
//true
System.out.println(student==student1);
}
複製程式碼
在主配置檔案中開啟二級快取(預設開啟,不配置也可以) sqlMapConfig.xml:
<?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">
<configuration>
<!-- 引入外部配置檔案-->
<properties resource="jdbcConfig.properties"></properties>
<!--設定開啟二級快取-->
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
<!--配置別名-->
<typeAliases>
<package name="com.hcx.domain"></package>
</typeAliases>
<!-- 配置環境-->
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</dataSource>
</environment>
</environments>
<!-- 指定帶有註解的dao介面所在位置 -->
<mappers>
<!--<mapper class="com.hcx.dao.StudentDao"></mapper>-->
<package name="com.hcx.dao"></package>
</mappers>
</configuration>
複製程式碼
在mapper中使用註解@CacheNamespace(blocking=true)
@CacheNamespace(blocking = true)
public interface StudentDao {
@Select("select * from student")
@Results(id = "studentMap",fetchType = FetchType.LAZY))
})
List<Student> findAll();
@Select("select * from student where id=#{id}")
@ResultMap(value = {"studentMap"})
Student findById(Integer id);
@Select("select * from student where name like #{name}")
@ResultMap(value = {"studentMap"})
List<Student> findStudentByName(String name);
}
複製程式碼
Test:
@Test
public void testFindOne(){
SqlSession sqlSession = factory.openSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
Student student = studentDao.findById(1);
System.out.println(student);
sqlSession.close();
SqlSession sqlSession1 = factory.openSession();
StudentDao studentDao1 = sqlSession1.getMapper(StudentDao.class);
Student student1 = studentDao1.findById(1);
System.out.println(student1);
sqlSession1.close();
//false
System.out.println(student==student1);
}
複製程式碼