1. 程式人生 > >Mybatis對映檔案(1)

Mybatis對映檔案(1)

mybatis對映檔案——增刪改查

public interface EmployeeMapper {
    Employee selectById(Integer id);
    void addEmp(Employee employee);
    void updateEmp(Employee employee);
    void deleteEmpById(Integer id);
}
<mapper namespace="dao.EmployeeMapper">
    <select id="selectById" resultType="employee">
SELECT * FROM t_employee WHERE id = #{id} </select> <!--parameterType可以省略--> <insert id="addEmp" parameterType="bean.Employee"> INSERT INTO t_employee VALUES (NULL ,#{lastName},#{gender},#{email}) </insert> <update id="updateEmp"> UPDATE t_employee SET last_name
= #{lastName},gender=#{gender},email = #{email} WHERE id=#{id} </update> <delete id="deleteEmpById"> DELETE FROM t_employee WHERE id=#{id} </delete> </mapper>
/**
 *1、 mybatis 允許增刪改查直接定義一下返回值型別
 *         Long、Integer、Boolean
 *2、我們需要手動提交資料
 *      sqlSessionFactory.openSession()===》手動提交
 *          sqlSessionFactory.openSession(true)===》自動提交
 
* @throws IOException */ @Test public void testSelect() throws IOException { SqlSession sqlSession = getSqlSession(); try { //3、獲取Employee的代理物件——通過sqlSession為介面建立一個代理物件 EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class); //增刪改查 mapper.addEmp(new Employee(null, "haha", "1", "[email protected]")); mapper.deleteEmpById(3); mapper.updateEmp(new Employee(1, "tona", "1", "[email protected]")); Employee e = mapper.selectById(2); System.out.println(e); } finally { //4、關閉SqlSession物件 sqlSession.close(); } }

獲取自增主鍵值的策略

自增的資料庫:MySQL

<!--
parameterType可以省略
mybatis支援自增主鍵、自增主鍵的獲取,mabatis也是利用statement.getGenereatedKeys()
useGeneratedKeys="true"使用主鍵自增獲取主鍵值策略
keyProperty:指定對應的主鍵屬性,也就是mybatis獲取到主鍵後,將這個值封裝給JavaBean的那個屬性
-->
<insert id="addEmp" parameterType="bean.Employee" useGeneratedKeys="true" keyProperty="id">
INSERT INTO t_employee(last_name, gender, email) VALUES (#{lastName},#{gender},#{email})
</insert>
非自增的資料庫:如Oracle
<!--oracle資料庫不支援自增-->
<!--使用Oracle-->
<insert id="addEmp" parameterType="bean.Employee" databaseId="oracle">
/*
    查詢主鍵的sql語句
    keyProperty:查出主鍵封裝給javaBean的那個屬性
    order="BEFORE":當前sql在插入sql之前執行
           AFTER:當前sql在插入sql之後執行
    resultType:查詢出的資料的返回值型別
    */
    <selectKey keyProperty="id" order="BEFORE" resultType="Integer">
SELECT EMPLOYEES_SEQ.nextval FROM dual
    </selectKey>
INSERT INTO t_employee(EMPLOYEE_ID,last_name, gender, email) VALUES (#{id},#{lastName},#{gender},#{email})
</insert>
mybatis引數處理

單個引數:mybatis不會做任何處理

               #{引數名}:取出引數的值

多個引數:mybatis會做特殊處理

                多個引數會被封裝成一個map

                key:param1,。。。。,paramN或者引數的索引也可以

                value:傳入的引數值

                #{ }就是從map中獲取指定的key值

Employee selectByIdAndLastName(Integer id,String lastNae);
<select id="selectByIdAndLastName" resultType="employee">
SELECT * FROM t_employee WHERE id = #{id} AND last_name=#{lastName}
</select>
出現異常: org.apache.ibatis.binding.BindingException: Parameter 'id' not found. Available parameters are [arg1, arg0, param1, param2]

改成:

<select id="selectByIdAndLastName" resultType="employee">
SELECT * FROM t_employee WHERE id = #{param1} AND last_name=#{param2}
</select>

程式執行OK。

推薦:

命名引數:明確指定封裝引數時的map的key:

@Param("id")

多個引數會被封裝成一個map

        key:使用@Param註解指定的值

        value:引數值

#{ }取出對應的引數值

Employee selectByIdAndLastName(@Param("id") Integer id,@Param("lastName") String lastName);
<select id="selectByIdAndLastName" resultType="employee">
SELECT * FROM t_employee WHERE id = #{id} AND last_name=#{lastName}
</select>

POJO:

如果多個引數正好時我們業務邏輯的資料模型,我們可以直接傳入pojo

        #{屬性名}:取出傳入的pojo的屬性值

Map:

如果多個引數不是業務模型中的資料,沒有對應的pojo,不經常使用,為了方便,我們也可以傳入map

        #{key}:取出map對應的值

TO:

如果多個引數不是業務模型中的資料,但是經常要使用,推薦來編寫一個TO(Transfer Object)資料傳輸物件

Page{

int index;

int size;

}

============小結==============

Employee getEmp(@Param("id") Integer id,String lastName);
取值:id==》#{id/param1}  lastName==》#{param2}
Employee getEmp(@Param("id") Integer id,@Param("e") Employee emp);
取值:id==》#{param1}  lastName==》#{param2.lastName/e.lastName}
###特別注意:如果是Collection(List,Set)型別或者是陣列,也會特殊處理。也是把傳入的list或陣列封裝在map中
key:Collection(collection),如果是List還可以使用key(list),陣列(array)
Employee getEmpById(List<Integer> ids);
取值:取出第一個值id==》#{ids[0]}  

==============原始碼——mybatis對引數的處理==============

public class ParamNameResolver {
    private static final String GENERIC_NAME_PREFIX = "param";
/**
     * 存放參數個數
     */
private final SortedMap<Integer, String> names;
    private boolean hasParamAnnotation;
//解析引數封裝成map
public ParamNameResolver(Configuration config, Method method) {
        final Class<?>[] paramTypes = method.getParameterTypes();
        final Annotation[][] paramAnnotations = method.getParameterAnnotations();
        final SortedMap<Integer, String> map = new TreeMap<Integer, String>();
        int paramCount = paramAnnotations.length;
// get names from @Param annotations
        //索引引數
for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) {
            if (isSpecialParameter(paramTypes[paramIndex])) {
                // skip special parameters
continue;
}
            String name = null;
//如果當前引數的註解為@Param註解
for (Annotation annotation : paramAnnotations[paramIndex]) {
                if (annotation instanceof Param) {
                    hasParamAnnotation = true;
name = ((Param) annotation).value();//獲取引數的值
break;
}
            }
            if (name == null) {
                // @Param was not specified.
if (config.isUseActualParamName()) {
                    name = getActualParamName(method, paramIndex);
}
                if (name == null) {
                    // use the parameter index as the name ("0", "1", ...)
                    // gcode issue #71
name = String.valueOf(map.size());//如果麼有標註解就是map
}
            }
            map.put(paramIndex, name);//放入
}
        names = Collections.unmodifiableSortedMap(map);
}

    private String getActualParamName(Method method, int paramIndex) {
        if (Jdk.parameterExists) {
            return ParamNameUtil.getParamNames(method).get(paramIndex);
}
        return null;
}

    private static boolean isSpecialParameter(Class<?> clazz) {
        return RowBounds.class.isAssignableFrom(clazz) || ResultHandler.class.isAssignableFrom(clazz);
}

    /**
     * Returns parameter names referenced by SQL providers.
     */
public String[] getNames() {
        return names.values().toArray(new String[0]);
}

    /**
     *  names (param1, param2,...).
     * </p>
*/
public Object getNamedParams(Object[] args) {
        final int paramCount = names.size();//獲取引數個數
if (args == null || paramCount == 0) {
            return null;//引數為null直接返回
            //如果只有一個元素,並且沒有param註解,直接返回args[0],單個元素直接返回
} else if (!hasParamAnnotation && paramCount == 1) {
            return args[names.firstKey()];
} else {
            final Map<String, Object> param = new ParamMap<Object>();
            int i = 0;
//給上面新建的param這個map儲存資料——遍歷names集合
for (Map.Entry<Integer, String> entry : names.entrySet()) {
                //names集合的value值作為key,names集合的key又作為取值的參考
                //如:names集合{0=id,1=lastName}===》{id=args[0]:1,lastName=args[1]:toma}
param.put(entry.getValue(), args[entry.getKey()]);
// add generic param names (param1, param2, ...)
                //額外的將每個引數儲存到map中,使用新的key:param1,param2。。。。paramN
final String genericParamName = GENERIC_NAME_PREFIX + String.valueOf(i + 1);
// ensure not to overwrite parameter named with @Param
if (!names.containsValue(genericParamName)) {
                    param.put(genericParamName, args[entry.getKey()]);
}
                i++;
}
            return param;
}
    }
}

ParamNameResolver解析引數封裝map的:

1、names獲取引數(0=id,1=lastName)

2、獲取每個表了@param註解的引數的值:id、lastName,賦值給name

3、每次解析一個引數給map中儲存資訊:(key:引數索引,value:name的值)

        name的值:標註了param註解:註解的值

        沒有標註:1、全域性配置isUseActualParamName(JDK1.8才行):name=引數名

                         2、name=map.size()——相當於當前元素的索引

===============關於引數的獲取================

#{ }:可以獲取map中的值或者pojo物件中的值

${ }:可以獲取map中的值或者pojo物件中的值

        區別:

<select id="selectByIdAndLastName" resultType="employee">
SELECT * FROM t_employee WHERE id = #{id} AND last_name=#{lastName}
</select>
執行的sql語句為: Preparing: SELECT * FROM t_employee WHERE id = ? AND last_name=?
<select id="selectByIdAndLastName" resultType="employee">
SELECT * FROM t_employee WHERE id = ${id} AND last_name=#{lastName}
</select>

執行的sql語句為:Preparing: SELECT * FROM t_employee WHERE id = 1 AND last_name=?

#{ }:是以預編譯的形式將引數設定到sql語句中,PrepareStatement。防止sql注入

${ }:將取出的值直接拼裝在sql中。會有安全問題

大多數情況下,我們取引數的值都應該使用#{ }

但是在原生jdbc不支援佔位符的地方就可以使用${ }進行取值

比如:分表:按照年份分表拆分

    select * from ${year}_salary where xxxx

    select * from employ order by ${ name } ${ desc/asc}——排序

#{ }:更豐富的用法:

        規定一些規則:

        javaType、jdbcType、mode(儲存過程)、numericScale(小數位數)、

        resultMap(結果集)、 typeHandler(型別處理器)、jdbcTypeName、express

jdbcType:通常需要在某些特定的條件下被設定:在我們資料為null的時候,有些資料庫可能不能識別mybatis對null的預設處理,比如oracle(報錯)——JdbcType OTHER:無效型別,因為mybatis對所有的null都對映的是原生jdbc的 Other型別

由於全域性配置中:jdbcTypeForNull=OTHER,Oracle不支援:——兩種解決:

1、#{ 引數,jdbcType=OTHER}     2、在全域性配置檔案中設定:jdbcTypeForNull=NULL

<setting name="jdbcTypeForNull" value="NULL"></setting>

相關推薦

Mybatis對映檔案1

mybatis對映檔案——增刪改查public interface EmployeeMapper { Employee selectById(Integer id); void addEmp(Employee employee); void updat

JavaEE-SSM:010 Mybatis對映1

對映器綜述   對映器是建立Mapper介面函式和Sql語句之間聯絡的關鍵部件,它可以指定POJO型別,也可以指定JDBC型別,同時,也可以指定TypeHandler對其轉換。可以對映Mapper介面函式引數:parameterType,也可對映結果引數ResultType或者Re

Mybatis對映檔案3

動態SQL1、if/where<!-- test:判斷表示式(OGNL自己去查怎麼用) test="id != null":從引數中取值進行判斷 拼裝的時候有的條件沒帶可能

Mybatis原始碼分析1—— Mapper檔案解析

感覺CSDN對markdown的支援不夠友好,總是伴隨各種問題,很惱火! xxMapper.xml的解析主要由XMLMapperBuilder類完成,parse方法來完成解析: public void parse() { if (!configuration.isRes

MyBatis原始碼分析1-MapConfig檔案的解析

1.簡述    MyBatis是一個優秀的輕ORM框架,由最初的iBatis演化而來,可以方便的完成sql語句的輸入輸出到java物件之間的相互對映,典型的MyBatis使用的方式如下: String resource = "org/mybatis/example/mybatis-config.xml";

Mybatis學習筆記1——第一個程式

暑期之前就有打算學習SSM,但是我記得當時再配置一個框架瘋狂報錯,弄得我很難受,,再加上當時有點其他事情,所以就放了下來。現在很有需求要會ssm,所以就學了一下。感覺框架這東西配置就煩的要死。錯一丁點就全錯。。下面開始說配置詳情。 介紹一下這些東西,將mybatis的jar包依賴放

JavaEE-SSM:014 Mybatis對映5

ResultMap子元素一覽     <constructor>節點配置   假如,我們返回型別的POJO不包含無參建構函式,只有一個下面的有參構造: public class RoleBean { public Rol

JavaEE-SSM:013 Mybatis對映4

SQL節點:一次定義,多次呼叫   先定義SQL節點:id用於參考 <sql id="preSql"> id,role_name,note </sql>   使用SQL: 通過include節點並指定refid,refid是

JavaEE-SSM:012 Mybatis對映3

1.insert節點配置資訊一覽   id用於Mapper介面函式的對應 parameterType指的是SQL語句的輸入引數 useGeneratedKeys自動產生主鍵 keyProperty主鍵欄位 KeyColumn主鍵列名   2.

JavaEE-SSM:011 Mybatis對映2

Select配置語句常用配置   常用的配置已經圈出: id:配合Mapper對映介面使用,一般和介面函式名稱一致 parameterType:輸入引數的型別 resultType:輸出引數的型別 ResultMap:輸出對映集 flushCache:清空快取

Redis配置檔案1units/includes/GENERAL/SECURITY/LIMITS

redis.conf檔案   在Linux進行檔案的檢視! units單位: 8 # Note on units: when memory size is needed, it is possible to specify 9 # it in the usual form

MyBatis學習筆記1---一個簡單MyBatis示例

利用JDBC仍舊存在的幾個侷限性: 在應用程式中存在的大量程式碼冗餘。 業務程式碼與資料庫訪問程式碼混雜在一起。 SQL語句與Java程式碼混雜在一起。 JDBC丟擲費力難懂的checked異常,需要程式設計師花費精力小心處理。 需要程式設計師自行解決ORM

Windows應用程式打包成exe檔案1- 工具簡單總結

最近有對一個Windows應用程式少許維護和修改。修改之後要釋出新的exe安裝檔案,打包exe檔案時,遇到了很頭疼的問題,還好最後解決了,記錄一下。 Visual Studio版本:Visual Studio 2017 Visual Studio 201

servlet載入配置檔案1

大三期間,和老師一起寫專案,發現一些小的技巧是之前沒有實現過:使用servlet啟動載入配置檔案,然後通過反射獲取物件的做法可以值得今後學習借用: <servlet> &

Mybatis配置檔案

Mapper檔案中各個標籤的含義Mapper檔案是Mybatis中SQL語句的配置檔案,其在執行時會載入SQL語句並對映相應引數。熟悉各個標籤的含義便於理解專案中DAO層相關函式的實際意義。屬性含義idSQL對映配置的唯一標識。parameterType傳入SQL配置中的引數

mybatis面試總結1——介紹mybatis

如果面試官直接讓我介紹mybatis,我將從以下幾個方面去介紹這個框架: 1.mybatis是什麼? mybatis是一個優秀的持久層框架,他對jdbc操作資料庫的過程進行了封裝,使

myBatis學習筆記1——快速入門

在專案中使用myBatis 匯入jar包 在src下建立配置檔案 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis

MyBatis原始碼學習1

MyBatis環境搭建 最近開始準備學習MyBatis的原始碼,第一件事當然就是搭建環境。 JDK:1.8 IDE:Idea mysql:8.0.11 首先需要安裝Git,正常下載安裝就可以,然後需要在Idea中配置一下,如下 圖:

深入Hibernate對映檔案——的屬性

<hibernate-mapping>根元素中可以指定以下屬性: (1)schema: 制定所對映的資料庫的Schema名, ()catalog ()default-casade:設定Hibernate預設的級聯風格,該屬性的預設值是none。當配置之Java屬

F28335的InitSysCtrl()與DSP2833x_SysCtrl.c檔案1

開發DSP除了CCS之外,TI還推出了一個controlSUITE,專門針對C2000系列,主要是官網資源的集中和分類。軟體免費只需要下載安裝,由於不喜歡被別人加工註釋了程式碼與工程,所以controlSUITE是個不錯的選擇。而且裡邊是TI原裝的東西,所以應該是最精華的!開