最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java的MyBatis框架中Mapper映射配置的使用及原理解析

 更新時間:2016年06月02日 09:46:41   作者:閑庭細步  
Mapper用于映射SQL語句,可以說是MyBatis操作數(shù)據(jù)庫的核心特性之一,這里我們來討論Java的MyBatis框架中Mapper映射配置的使用及原理解析,包括對mapper的xml配置文件的讀取流程解讀.

Mapper的內(nèi)置方法
model層就是實體類,對應數(shù)據(jù)庫的表。controller層是Servlet,主要是負責業(yè)務(wù)模塊流程的控制,調(diào)用service接口的方法,在struts2就是Action。Service層主要做邏輯判斷,Dao層是數(shù)據(jù)訪問層,與數(shù)據(jù)庫進行對接。至于Mapper是mybtis框架的映射用到,mapper映射文件在dao層用。

下面是介紹一下Mapper的內(nèi)置方法:

1、countByExample ===>根據(jù)條件查詢數(shù)量

int countByExample(UserExample example);
 
//下面是一個完整的案列
UserExample example = new UserExample();
 Criteria criteria = example.createCriteria();
 criteria.andUsernameEqualTo("joe");
 int count = userDAO.countByExample(example);

 相當于:select count(*) from user where username='joe'
 
2、deleteByExample ===>根據(jù)條件刪除多條

int deleteByExample(AccountExample example);
 
//下面是一個完整的案例
UserExample example = new UserExample();
 Criteria criteria = example.createCriteria();
 criteria.andUsernameEqualTo("joe");
 userDAO.deleteByExample(example);
 相當于:delete from user where username='joe'

3、deleteByPrimaryKey===>根據(jù)條件刪除單條

int deleteByPrimaryKey(Integer id);
userDAO.deleteByPrimaryKey(101); 

相當于:

delete from user where id=101
 

4、insert===>插入數(shù)據(jù)

int insert(Account record);
 
//下面是完整的案例
User user = new User();
 //user.setId(101);
 user.setUsername("test");
 user.setPassword("123456")
 user.setEmail("674531003@qq.com");
 userDAO.insert(user);

 相當于:

insert into user(ID,username,password,email) values(101,'test','123456','674531003@qq.com');

 5、insertSelective===>插入數(shù)據(jù)

int insertSelective(Account record);

6、selectByExample===>根據(jù)條件查詢數(shù)據(jù)

List<Account> selectByExample(AccountExample example);
 
//下面是一個完整的案例
UserExample example = new UserExample();
Criteria criteria = example.createCriteria();
criteria.andUsernameEqualTo("joe");
criteria.andUsernameIsNull();
example.setOrderByClause("username asc,email desc");
List<?>list = userDAO.selectByExample(example);
相當于:select * from user where username = 'joe' and username is null order by username asc,email desc
 
//注:在iBator 生成的文件UserExample.java中包含一個static 的內(nèi)部類 Criteria ,在Criteria中有很多方法,主要是定義SQL 語句where后的查詢條件。

 7、selectByPrimaryKey===>根據(jù)主鍵查詢數(shù)據(jù)

Account selectByPrimaryKey(Integer id);//相當于select * from user where id = 變量id

 
8、updateByExampleSelective===>按條件更新值不為null的字段

int updateByExampleSelective(@Param("record") Account record, @Param("example") AccountExample example);
 
//下面是一個完整的案列
UserExample example = new UserExample();
 Criteria criteria = example.createCriteria();
 criteria.andUsernameEqualTo("joe");
 User user = new User();
 user.setPassword("123");
 userDAO.updateByPrimaryKeySelective(user,example);
 相當于:update user set password='123' where username='joe'

 
9、updateByExampleSelective===>按條件更新

int updateByExample(@Param("record") Account record, @Param("example") AccountExample example);

10、updateByPrimaryKeySelective===>按條件更新

int updateByPrimaryKeySelective(Account record);

//下面是一個完整的案例

 User user = new User();
user.setId(101);
user.setPassword("joe");
userDAO.updateByPrimaryKeySelective(user);

相當于:

update user set password='joe' where id=101
int updateByPrimaryKeySelective(Account record);
 
//下面是一個完整的案例
 
 User user = new User();
user.setId(101);
user.setPassword("joe");
userDAO.updateByPrimaryKeySelective(user);

相當于:update user set password='joe' where id=101

11、updateByPrimaryKey===>按主鍵更新

int updateByPrimaryKey(Account record);

//下面是一個完整的案例
User user =new User();
 user.setId(101);
 user.setUsername("joe");
 user.setPassword("joe");
 user.setEmail("joe@163.com");
 userDAO.updateByPrimaryKey(user);

 相當于:

update user set username='joe',password='joe',email='joe@163.com' where id=101
int updateByPrimaryKey(Account record);
 
//下面是一個完整的案例
User user =new User();
 user.setId(101);
 user.setUsername("joe");
 user.setPassword("joe");
 user.setEmail("joe@163.com");
 userDAO.updateByPrimaryKey(user);

 相當于:

update user set username='joe',password='joe',email='joe@163.com' where id=101

 
解析mapper的xml配置文件
我們來看看mybatis是怎么讀取mapper的xml配置文件并解析其中的sql語句。

我們還記得是這樣配置sqlSessionFactory的:

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">   
  <property name="dataSource" ref="dataSource" />  
  <property name="configLocation" value="classpath:configuration.xml"></property>   
  <property name="mapperLocations" value="classpath:com/xxx/mybatis/mapper/*.xml"/>   
  <property name="typeAliasesPackage" value="com.tiantian.mybatis.model" />   
</bean>  

這里配置了一個mapperLocations屬性,它是一個表達式,sqlSessionFactory會根據(jù)這個表達式讀取包com.xxx.mybaits.mapper下面的所有xml格式文件,那么具體是怎么根據(jù)這個屬性來讀取配置文件的呢?

答案就在SqlSessionFactoryBean類中的buildSqlSessionFactory方法中:

if (!isEmpty(this.mapperLocations)) { 
   for (Resource mapperLocation : this.mapperLocations) { 
    if (mapperLocation == null) { 
     continue; 
    } 
 
    try { 
     XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(), 
       configuration, mapperLocation.toString(), configuration.getSqlFragments()); 
     xmlMapperBuilder.parse(); 
    } catch (Exception e) { 
     throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation + "'", e); 
    } finally { 
     ErrorContext.instance().reset(); 
    } 
 
    if (logger.isDebugEnabled()) { 
     logger.debug("Parsed mapper file: '" + mapperLocation + "'"); 
    } 
   } 
  } 

mybatis使用XMLMapperBuilder類的實例來解析mapper配置文件。

public XMLMapperBuilder(Reader reader, Configuration configuration, String resource, Map<String, XNode> sqlFragments) { 
  this(new XPathParser(reader, true, configuration.getVariables(), new XMLMapperEntityResolver()), 
    configuration, resource, sqlFragments); 
 } 

private XMLMapperBuilder(XPathParser parser, Configuration configuration, String resource, Map<String, XNode> sqlFragments) { 
  super(configuration); 
  this.builderAssistant = new MapperBuilderAssistant(configuration, resource); 
  this.parser = parser; 
  this.sqlFragments = sqlFragments; 
  this.resource = resource; 
 } 

接著系統(tǒng)調(diào)用xmlMapperBuilder的parse方法解析mapper。

public void parse() { 
  //如果configuration對象還沒加載xml配置文件(避免重復加載,實際上是確認是否解析了mapper節(jié)點的屬性及內(nèi)容, 
  //為解析它的子節(jié)點如cache、sql、select、resultMap、parameterMap等做準備), 
  //則從輸入流中解析mapper節(jié)點,然后再將resource的狀態(tài)置為已加載 
  if (!configuration.isResourceLoaded(resource)) { 
   configurationElement(parser.evalNode("/mapper")); 
   configuration.addLoadedResource(resource); 
   bindMapperForNamespace(); 
  } 
  //解析在configurationElement函數(shù)中處理resultMap時其extends屬性指向的父對象還沒被處理的<resultMap>節(jié)點 
  parsePendingResultMaps(); 
  //解析在configurationElement函數(shù)中處理cache-ref時其指向的對象不存在的<cache>節(jié)點(如果cache-ref先于其指向的cache節(jié)點加載就會出現(xiàn)這種情況) 
  parsePendingChacheRefs(); 
  //同上,如果cache沒加載的話處理statement時也會拋出異常 
  parsePendingStatements(); 
 } 

mybatis解析mapper的xml文件的過程已經(jīng)很明顯了,接下來我們看看它是怎么解析mapper的:

private void configurationElement(XNode context) { 
  try { 
   //獲取mapper節(jié)點的namespace屬性 
   String namespace = context.getStringAttribute("namespace"); 
   if (namespace.equals("")) { 
    throw new BuilderException("Mapper's namespace cannot be empty"); 
   } 
   //設(shè)置當前namespace 
   builderAssistant.setCurrentNamespace(namespace); 
   //解析mapper的<cache-ref>節(jié)點 
   cacheRefElement(context.evalNode("cache-ref")); 
   //解析mapper的<cache>節(jié)點 
   cacheElement(context.evalNode("cache")); 
   //解析mapper的<parameterMap>節(jié)點 
   parameterMapElement(context.evalNodes("/mapper/parameterMap")); 
   //解析mapper的<resultMap>節(jié)點 
   resultMapElements(context.evalNodes("/mapper/resultMap")); 
   //解析mapper的<sql>節(jié)點 
   sqlElement(context.evalNodes("/mapper/sql")); 
   //使用XMLStatementBuilder的對象解析mapper的<select>、<insert>、<update>、<delete>節(jié)點, 
   //mybaits會使用MappedStatement.Builder類build一個MappedStatement對象, 
   //所以mybaits中一個sql對應一個MappedStatement 
   buildStatementFromContext(context.evalNodes("select|insert|update|delete")); 
  } catch (Exception e) { 
   throw new BuilderException("Error parsing Mapper XML. Cause: " + e, e); 
  } 
 } 

configurationElement函數(shù)幾乎解析了mapper節(jié)點下所有子節(jié)點,至此mybaits解析了mapper中的所有節(jié)點,并將其加入到了Configuration對象中提供給sqlSessionFactory對象隨時使用。這里我們需要補充講一下mybaits是怎么使用XMLStatementBuilder類的對象的parseStatementNode函數(shù)借用MapperBuilderAssistant類對象builderAssistant的addMappedStatement解析MappedStatement并將其關(guān)聯(lián)到Configuration類對象的:

public void parseStatementNode() { 
  //ID屬性 
  String id = context.getStringAttribute("id"); 
  //databaseId屬性 
  String databaseId = context.getStringAttribute("databaseId"); 
 
  if (!databaseIdMatchesCurrent(id, databaseId, this.requiredDatabaseId)) { 
   return; 
  } 
  //fetchSize屬性 
  Integer fetchSize = context.getIntAttribute("fetchSize"); 
  //timeout屬性 
  Integer timeout = context.getIntAttribute("timeout"); 
  //parameterMap屬性 
  String parameterMap = context.getStringAttribute("parameterMap"); 
  //parameterType屬性 
  String parameterType = context.getStringAttribute("parameterType"); 
  Class<?> parameterTypeClass = resolveClass(parameterType); 
  //resultMap屬性 
  String resultMap = context.getStringAttribute("resultMap"); 
  //resultType屬性 
  String resultType = context.getStringAttribute("resultType"); 
  //lang屬性 
  String lang = context.getStringAttribute("lang"); 
  LanguageDriver langDriver = getLanguageDriver(lang); 
 
  Class<?> resultTypeClass = resolveClass(resultType); 
  //resultSetType屬性 
  String resultSetType = context.getStringAttribute("resultSetType"); 
  StatementType statementType = StatementType.valueOf(context.getStringAttribute("statementType", StatementType.PREPARED.toString())); 
  ResultSetType resultSetTypeEnum = resolveResultSetType(resultSetType); 
 
  String nodeName = context.getNode().getNodeName(); 
  SqlCommandType sqlCommandType = SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH)); 
  //是否是<select>節(jié)點 
  boolean isSelect = sqlCommandType == SqlCommandType.SELECT; 
  //flushCache屬性 
  boolean flushCache = context.getBooleanAttribute("flushCache", !isSelect); 
  //useCache屬性 
  boolean useCache = context.getBooleanAttribute("useCache", isSelect); 
  //resultOrdered屬性 
  boolean resultOrdered = context.getBooleanAttribute("resultOrdered", false); 
 
  // Include Fragments before parsing 
  XMLIncludeTransformer includeParser = new XMLIncludeTransformer(configuration, builderAssistant); 
  includeParser.applyIncludes(context.getNode()); 
 
  // Parse selectKey after includes and remove them. 
  processSelectKeyNodes(id, parameterTypeClass, langDriver); 
   
  // Parse the SQL (pre: <selectKey> and <include> were parsed and removed) 
  SqlSource sqlSource = langDriver.createSqlSource(configuration, context, parameterTypeClass); 
  //resultSets屬性 
  String resultSets = context.getStringAttribute("resultSets"); 
  //keyProperty屬性 
  String keyProperty = context.getStringAttribute("keyProperty"); 
  //keyColumn屬性 
  String keyColumn = context.getStringAttribute("keyColumn"); 
  KeyGenerator keyGenerator; 
  String keyStatementId = id + SelectKeyGenerator.SELECT_KEY_SUFFIX; 
  keyStatementId = builderAssistant.applyCurrentNamespace(keyStatementId, true); 
  if (configuration.hasKeyGenerator(keyStatementId)) { 
   keyGenerator = configuration.getKeyGenerator(keyStatementId); 
  } else { 
   //useGeneratedKeys屬性 
   keyGenerator = context.getBooleanAttribute("useGeneratedKeys", 
     configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType)) 
     ? new Jdbc3KeyGenerator() : new NoKeyGenerator(); 
  } 
 
  builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType, 
    fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass, 
    resultSetTypeEnum, flushCache, useCache, resultOrdered,  
    keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets); 
 } 

由以上代碼可以看出mybaits使用XPath解析mapper的配置文件后將其中的resultMap、parameterMap、cache、statement等節(jié)點使用關(guān)聯(lián)的builder創(chuàng)建并將得到的對象關(guān)聯(lián)到configuration對象中,而這個configuration對象可以從sqlSession中獲取的,這就解釋了我們在使用sqlSession對數(shù)據(jù)庫進行操作時mybaits怎么獲取到mapper并執(zhí)行其中的sql語句的問題。

相關(guān)文章

  • My eclipse 端口占用(9360)問題解決辦法

    My eclipse 端口占用(9360)問題解決辦法

    這篇文章主要介紹了My eclipse 工程發(fā)布時出現(xiàn)端口占用問題解決辦法的相關(guān)資料,需要的朋友可以參考下
    2016-12-12
  • Java結(jié)構(gòu)型設(shè)計模式之適配器模式詳解

    Java結(jié)構(gòu)型設(shè)計模式之適配器模式詳解

    適配器模式,即將某個類的接口轉(zhuǎn)換成客戶端期望的另一個接口的表示,主要目的是實現(xiàn)兼容性,讓原本因為接口不匹配,沒辦法一起工作的兩個類,可以協(xié)同工作。本文將通過示例詳細介紹適配器模式,需要的可以參考一下
    2022-09-09
  • Spring使用注解方式處理事務(wù)

    Spring使用注解方式處理事務(wù)

    這篇文章主要為大家詳細介紹了Spring使用注解方式處理事務(wù),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • SpringBoot對Druid配置SQL監(jiān)控功能失效問題及解決方法

    SpringBoot對Druid配置SQL監(jiān)控功能失效問題及解決方法

    這篇文章主要介紹了SpringBoot對Druid配置SQL監(jiān)控功能失效問題的解決方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-05-05
  • Java生成隨機數(shù)的2種示例方法代碼

    Java生成隨機數(shù)的2種示例方法代碼

    在Java中,生成隨機數(shù)有兩種方法。1是使用Random類。2是使用Math類中的random方法??聪旅娴睦邮褂冒?/div> 2013-11-11
  • SpringBoot整合Spring Security的詳細教程

    SpringBoot整合Spring Security的詳細教程

    這篇文章主要介紹了SpringBoot整合Spring Security的方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-08-08
  • Java設(shè)計模式之觀察者模式

    Java設(shè)計模式之觀察者模式

    本文詳細講解了Java設(shè)計模式之觀察者模式,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-09-09
  • Scala求和示例代碼

    Scala求和示例代碼

    這篇文章主要介紹了Scala求和示例代碼,需要的朋友可以參考下
    2019-06-06
  • Java編寫實現(xiàn)坦克大戰(zhàn)小游戲

    Java編寫實現(xiàn)坦克大戰(zhàn)小游戲

    這篇文章主要為大家詳細介紹了Java編寫實現(xiàn)坦克大戰(zhàn)小游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • SpringMvc直接接收json數(shù)據(jù)自動轉(zhuǎn)化為Map的實例

    SpringMvc直接接收json數(shù)據(jù)自動轉(zhuǎn)化為Map的實例

    今天小編就為大家分享一篇SpringMvc直接接收json數(shù)據(jù)自動轉(zhuǎn)化為Map的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-08-08

最新評論

读书| 永平县| 江西省| 唐河县| 日喀则市| 新乡市| 犍为县| 昌宁县| 红桥区| 双辽市| 镇江市| 肥城市| 泰安市| 泗水县| 伊金霍洛旗| 舞钢市| 玉山县| 郸城县| 呼伦贝尔市| 黎城县| 陇南市| 麻江县| 承德市| 龙州县| 辽宁省| 榕江县| 延吉市| 邮箱| 阳春市| 于都县| 扎囊县| 友谊县| 盐津县| 鄂伦春自治旗| 闵行区| 富顺县| 镇宁| 新郑市| 兴文县| 井陉县| 林口县|