MyBatis註解Annotation介紹及Demo

MyBatis可以利用SQL映射文件來配置,也可以利用Annotation來設置。MyBatis提供的一些基本註解如下表所示。

註解

目標

相應的XML

描述

@CacheNamespace

<cache>  

爲給定的命名空間(比如類)配置緩存。屬性:

implemetation,eviction,

flushInterval , size readWrite

@CacheNamespaceRef

<cacheRef>

參照另外一個命名空間的緩存來使用。

屬性:value,也就是類的完全限定名。

@ConstructorArgs

方法

<constructor>

收集一組結果傳遞給對象構造方法。

屬性:value,是形式參數的數組

@Arg

方法

<arg>

<idArg>


單獨的構造方法參數,是ConstructorArgs  集合的一部分。屬性:id,column,javaTypetypeHandler

id屬性是布爾值,來標識用於比較的屬性,和<idArg>XML 元素相似

@TypeDiscriminator

方法

<discriminator>

一組實例值被用來決定結果映射的表

現。屬性:Column, javaType ,  jdbcType typeHandlercases

cases屬性就是實例的數組。

@Case

方法

<case>

單獨實例的值和它對應的映射。屬性:value  type results

Results 屬性是結果數組,因此這個註解和實際的ResultMap 很相似,由下面的  Results註解指定

@Results

方法

<resultMap>

結果映射的列表,包含了一個特別結果

列如何被映射到屬性或字段的詳情。

屬性:value ,是Result註解的數組

@Result

方法

<result>

<id>

在列和屬性或字段之間的單獨結果映

射。屬性:id column property

javaType jdbcType type Handler

onemanyid 屬性是一個布爾值,表

示了應該被用於比較的屬性。one 屬性是單獨的聯繫,和 <association> 相似,而many 屬性是對集合而言的,和

<collection>相似。

@One

方法

<association>  

複雜類型的單獨屬性值映射。屬性:

select,已映射語句(也就是映射器方

法)的完全限定名,它可以加載合適類

型的實例。注意:聯合映射在註解 API

中是不支持的。

@Many

方法

<collection>

複雜類型的集合屬性映射。屬性:

select,是映射器方法的完全限定名,它可加載合適類型的一組實例。注意:聯合映射在 Java註解中是不支持的。

@Options

方法

映射語句的屬性

這個註解提供訪問交換和配置選項的寬廣範圍,它們通常在映射語句上作爲屬性出現。而不是將每條語句註解變複雜,Options 註解提供連貫清晰的方式來訪問它們。屬性:useCache=true

flushCache=false

resultSetType=FORWARD_ONLY

statementType=PREPARED

fetchSize= -1timeout=-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

指定的方法. 這個方法可以選擇性的接

受參數對象作爲它的唯一參數,但是必

須只指定該參數或者沒有參數。屬性:

typemethodtype 屬性是類的完全限定名。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。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章