<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Mybatis介紹之參數(shù)傳遞

       

      1     使用Mapper接口時參數(shù)傳遞方式

             Mybatis在使用Mapper接口進行編程時,其實底層是采用了動態(tài)代理機制,表面上是調(diào)用的Mapper接口,而實際上是通過動態(tài)代理調(diào)用的SqlSession的對應(yīng)方法,如selectOne(),有興趣的朋友可以查看DefaultSqlSession的getMapper()方法實現(xiàn),其最終會獲得一個代理了Mapper接口的MapperProxy對象。MapperProxy對象在調(diào)用Mapper接口方法時會把傳遞的參數(shù)做一個轉(zhuǎn)換,然后把轉(zhuǎn)換后的參數(shù)作為入?yún)⒄{(diào)用SqlSession對應(yīng)的操作方法(如selectOne、insert等)。轉(zhuǎn)換過程可以參考MapperMethod的execute()方法實現(xiàn)。簡單來說是以下規(guī)則:

      1、如果傳遞過來是單參數(shù),且沒有以@Param注解進行命名,則直接將單參數(shù)作為真實的參數(shù)調(diào)用SqlSession的對應(yīng)方法。

      2、如果傳遞過來的不是單參數(shù)或者是包含以@Param注解進行命名的參數(shù),則會將對應(yīng)的參數(shù)轉(zhuǎn)換為一個Map進行傳遞。具體規(guī)則如下:

      2.1、      會把對應(yīng)的參數(shù)按照順序以param1、param2、paramN這樣的形式作為Key存入目標(biāo)Map中,第一個參數(shù)是param1,第N個參數(shù)是paramN。

      2.2、      如果參數(shù)是以@Param注解命名的參數(shù),則以@Param指定的名稱作為Key存入目標(biāo)Map中。

      2.3、      如果參數(shù)不是以@Param注解命名的,則按照順序以0、1、N這樣的形式作為Key存入目標(biāo)Map中,第一個參數(shù)是0,第N個參數(shù)是N。

       

             我們在Mapper.xml中定義SQL語句中用到的變量最終是以Mybatis按照上述規(guī)則把入?yún)⑥D(zhuǎn)換后的形式來進行解析的。

       

      2     參數(shù)引用#與$的區(qū)別

             在Mybatis的Mapper.xml文件中為了構(gòu)建動態(tài)的SQL,我們通常需要通過引用傳遞的參數(shù)來達到對應(yīng)的效果。在引用傳遞的參數(shù)的時候有兩種方式,一種是通過“#{var}”的形式引用,一種是通過“${var}”的形式引用。前者會被以預(yù)編譯的方式傳遞,即會生成PreparedStatement來處理,對應(yīng)的參數(shù)在SQL中會以“?”占位,然后調(diào)用PreparedStatement的相應(yīng)API設(shè)值;而后者則會先處理好變量再執(zhí)行相應(yīng)的SQL,即對應(yīng)的變量會先被替換,再執(zhí)行替換了變量的SQL。在一個Mapper映射語句中我們可以同時使用“#”和“$”處理變量。

       

      3     采用#{var}的形式處理變量

             采用#{var}的形式來引用變量時,其中的變量會在解析Mapper.xml文件中的語句時就被替換為占位符“?”,同時通過ParameterMapping類記錄對應(yīng)的變量信息。在真正執(zhí)行對應(yīng)的語句時會用傳遞的真實參數(shù)根據(jù)ParameterMapping信息給PreparedStatement設(shè)置參數(shù),具體可參考PreparedStatementHandler的parameterize()方法實現(xiàn)。對應(yīng)的變量在解析的時候都是以傳遞進來的參數(shù)為基礎(chǔ)來解析的,根據(jù)前面的介紹我們知道,傳遞進來的參數(shù)只有兩種情況,一種是原始類型的單參數(shù),一種是被Mybatis封裝過的Map。那對應(yīng)的參數(shù)Mybatis的如何解析的呢?有三種情況。

             第一種,如果真實傳遞進來的是原始類型,那么對應(yīng)的屬性解析就是就是基于原始類型的屬性。比如我們真是傳遞進來的一個User類型的對象,User對象有id、name等屬性,那么我們在Mapper語句中采用#{var}形式訪問變量的時候就可以使用#{id}和#{name}。這跟使用${var}形式訪問變量是不同的,使用${var}形式時我們需要使用${_parameter.id}和${_parameter.name}。

         <insert id="insert"parameterType="com.elim.learn.mybatis.model.User"useGeneratedKeys="true" keyColumn="id" keyProperty="id">

            insert into t_user(name,username,email,mobile) values(#{name},#{username},#{email},#{mobile})

         </insert>

       

             第二種,如果真實傳遞進來的是一個Map,那么對應(yīng)的變量則可以是這個Map里面的Key。比如下面示例中我們的接口方法對應(yīng)的是兩個參數(shù),那最終到執(zhí)行Mapper語句時會被封裝成一個Map,Map里面的Key包含name、1、param1和param2,那么我們在使用的時候就可以使用這些變量。

         List<User> findByNameAndMobile(@Param("name") String name, Stringmobile);

       

         <select id="findByNameAndMobile"resultType="com.elim.learn.mybatis.model.User">

            select id,name,username,email,mobile from t_user where name=#{name} and mobile=#{1}

         </select>

       

             第三種,真實傳遞進來的參數(shù)是可以被已經(jīng)注冊了的TypeHandler進行處理的,則直接使用真實傳遞進來的參數(shù)作為真實的變量值。這也是為什么我們經(jīng)常可以在Mapper接口里面寫delete(Integer id),然后在Mapper語句中直接寫#{id}的原因,因為這個時候傳遞進來的參數(shù)是Integer類型,是可以直接被處理的,Mybatis將直接拿它的值作為當(dāng)前變量id的值,而不會去取傳遞進來的值的id屬性。換句話說,這個時候我們在Mapper語句中定義的變量可以隨便命名,隨便怎么命名都可以被Mybatis正確的處理。但是通常我們會把它命名為與接口方法參數(shù)名稱一致,方便閱讀。

         void delete(Long id);

       

         <insert id="delete" parameterType="java.lang.Long">

            delete t_user where id=#{id}

         </insert>

       

             關(guān)于預(yù)編譯的參數(shù)處理是由DefaultParameterHandler類的setParameters()方法處理,核心代碼如下,欲了解更多,可以參考DefaultParameterHandler的完整代碼。

        public void setParameters(PreparedStatement ps) {

          ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());

          List<ParameterMapping> parameterMappings =boundSql.getParameterMappings();

          if (parameterMappings != null) {

            for (inti = 0; i < parameterMappings.size(); i++) {

              ParameterMapping parameterMapping = parameterMappings.get(i);

              if (parameterMapping.getMode() != ParameterMode.OUT) {

                Object value;

                String propertyName = parameterMapping.getProperty();

                if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params

                  value = boundSql.getAdditionalParameter(propertyName);

                } else if (parameterObject == null) {

                  value = null;

                } else if(typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {

                  value = parameterObject;

                } else {

                  MetaObject metaObject =configuration.newMetaObject(parameterObject);

                  value = metaObject.getValue(propertyName);

                }

                TypeHandler typeHandler = parameterMapping.getTypeHandler();

                JdbcType jdbcType = parameterMapping.getJdbcType();

                if (value == null && jdbcType == null) {

                  jdbcType = configuration.getJdbcTypeForNull();

                }

                try {

                  typeHandler.setParameter(ps, i + 1, value, jdbcType);

                } catch (TypeException e) {

                  throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);

                } catch (SQLException e) {

                  throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);

                }

              }

            }

          }

        }

       

      4     采用${var}的形式處理變量

             采用“${var}”的形式來引用變量時,其中的變量會在MappedStatement調(diào)用getBoundSql()方法獲取對應(yīng)的BoundSql時被替換。${var}中的var可以是如下取值:

      1、內(nèi)置的_parameter變量,對應(yīng)轉(zhuǎn)換后的傳遞參數(shù),在只傳遞單參數(shù)且是沒有使用@Param注解對參數(shù)命名的時候如果我們需要通過${var}的形式來訪問傳遞的單參數(shù),則可以使用${_parameter};

      2、如果對應(yīng)的Mapper接口方法是多參數(shù)或者擁有@Param命名的參數(shù)時可以使用param1、paramN的形式;

      3、如果對應(yīng)的Mapper接口方法參數(shù)是@Param命名的方法參數(shù),則可以使用@Param指定的名稱;

      4、如果對應(yīng)的Mapper接口方法擁有多個參數(shù),且擁有沒有使用@Param命名的參數(shù),那沒有使用@Param命名的參數(shù)可以通過0、1、N形式訪問。

       

             根據(jù)上述規(guī)則如我們有一個findById的方法其接收一個Long類型的參數(shù)作為ID,當(dāng)使用${var}的形式引用變量時則可以寫成如下這樣:

         <select id="findById"resultType="com.elim.learn.mybatis.model.User"parameterType="java.lang.Long" >

            select id,name,username,email,mobile from t_user where id=${_parameter}

         </select>

       

             當(dāng)我們的Mapper接口方法參數(shù)使用了@Param命名的時候,我們還可以使用@Param指定的參數(shù)名。

      public interface UserMapper {

         User findById(@Param("id") Long id);

      }

       

         <select id="findById"resultType="com.elim.learn.mybatis.model.User"parameterType="java.lang.Long" >

            select id,name,username,email,mobile from t_user where id=${id}

         </select>

             注意,但是使用了@Param對單參數(shù)命名后我們就不能再在Mapper語句中通過${_parameter}來引用接口方法參數(shù)傳遞過來的單參數(shù)了,因為此時其已經(jīng)被包裝為一個Map了,如果要通過_parameter來引用的話,我們應(yīng)該使用${_parameter.param1}或${_parameter.varName},對于上面的示例來說就是${_parameter.param1}或${_parameter.id}。

       

             下面我們來看一個傳遞多參數(shù)的,假設(shè)我們有如下這樣的一個Mapper語句及對應(yīng)的Mapper接口方法,這個Mapper接口方法接收兩個參數(shù),第一個參數(shù)是用@Param注解指定了參數(shù)名為name,第二個參數(shù)是沒有使用注解的,具體如下。

         <!-- 當(dāng)對應(yīng)的接口方法傳遞多個參數(shù)時,可以不指定parameterType參數(shù),就算指定了也沒用,因為這個時候默認是Map -->

         <select id="findByNameAndMobile"resultType="com.elim.learn.mybatis.model.User">

            select id,name,username,email,mobile from t_user where name='${name}' and mobile='${1}'

         </select>

       

         List<User> findByNameAndMobile(@Param("name") String name, Stringmobile);

       

           那我們的Mapper.xml文件中的對應(yīng)語句需要Mapper接口方法參數(shù)時有哪幾種方式呢?按照之前的規(guī)則,對于第一個方法參數(shù)name而言,因為使用了@Param指定了參數(shù)名name,所以我們可以在Mapper.xml文件中通過變量name和param1來引用它,而第二個參數(shù)mobile是沒有使用@Param指定參數(shù)名的,則我們可以使用param2和參數(shù)相對位置“1”來引用它。如上面的示例中,我們就是通過第二個參數(shù)的相對位置“1”來引用的。如果我們把第二個參數(shù)改為${mobile}是引用不到,且系統(tǒng)會報如下錯誤,有興趣的朋友可以試一下。

      org.apache.ibatis.binding.BindingException: Parameter 'mobile' not found. Available parameters are [1, name, param1, param2]

       

             一般情況下為了防止SQL注入問題,是不建議直接在where條件中使用${var}的形式訪問變量的,通常會用預(yù)編譯形式的#{var}。而${var}往往是用來傳遞一些非where條件的內(nèi)容,比如排序信息,具體用法請根據(jù)實際情況決定。

      posted @ 2018-04-13 10:21  舊雨衣  閱讀(2718)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国产在线精品一区二区夜色| 好吊视频一区二区三区| 中文字幕av中文字无码亚 | 亚洲 制服 丝袜 无码| 中文字幕日韩精品人妻| 日本国产精品第一页久久| 亚洲国产五月综合网| 东京热人妻中文无码| 国产午夜在线观看视频播放| 日韩秘 无码一区二区三区 | 九九热在线观看精品视频| 久久一日本综合色鬼综合色| 久久人人97超碰国产精品| 好大好硬好爽免费视频| 成人区人妻精品一区二区| 在线a级毛片无码免费真人| 国产午夜精品福利视频| 麻豆蜜桃av蜜臀av色欲av| av 日韩 人妻 黑人 综合 无码| gogogo高清在线播放免费| 亚洲gv猛男gv无码男同| 成人av一区二区亚洲精| 久章草在线毛片视频播放| 亚洲成人高清av在线| 国产办公室秘书无码精品99| 中文字幕无码人妻aaa片| 人妻少妇精品视频专区| 欧美人禽杂交狂配| 久久国产精品色av免费看| 在线中文一区字幕对白| 亚洲香蕉网久久综合影视| 欧美大肥婆大肥bbbbb| 国内自拍小视频在线看| 毛片亚洲AV无码精品国产午夜| 国产亚洲精品aaaa片app| 国产福利片一区二区三区| 亚洲AV国产福利精品在现观看| 亚洲乱色熟女一区二区蜜臀| 国产在线观看免费观看| 色偷偷亚洲男人的天堂| 日韩精品一区二区高清视频|