MyBatis能夠利用SQL映射文件來配置,也能夠利用Annotation來設置。MyBatis提供的一些基本註解以下表所示。
java
註解spring |
目標sql |
相應的XML數據庫 |
描述apache |
@CacheNamespace數組 |
類緩存 |
<cache> session |
爲給定的命名空間(好比類)配置緩存。屬性:mybatis implemetation,eviction,app 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:
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:
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語句
映射器接口註解
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); }
測試代碼:
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進行執行
映射器接口
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生成)
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以下。
<?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。
<mappers> <mapper resource="com/whut/model/Blog.xml"/> </mappers>
測試類
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。