欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

Mapper的內(nèi)置方法
model層就是實體類,對應(yīng)數(shù)據(jù)庫的表。controller層是Servlet,主要是負(fù)責(zé)業(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);

 相當(dāng)于: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);
 相當(dāng)于:delete from user where username='joe'

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

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

相當(dāng)于:

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);

 相當(dāng)于:

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);
相當(dāng)于: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);//相當(dāng)于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);
 相當(dāng)于: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);

相當(dāng)于:

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);

相當(dāng)于: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);

 相當(dāng)于:

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);

 相當(dāng)于:

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配置文件(避免重復(fù)加載,實際上是確認(rèn)是否解析了mapper節(jié)點的屬性及內(nèi)容, 
  //為解析它的子節(jié)點如cache、sql、select、resultMap、parameterMap等做準(zhǔn)備), 
  //則從輸入流中解析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è)置當(dāng)前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對應(yīng)一個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)文章

  • springboot中使用groovy的示例代碼

    springboot中使用groovy的示例代碼

    Groovy就是一種繼承了動態(tài)語言的優(yōu)良特性并運行在JVM上的編程語言,Groovy支持動態(tài)輸入,閉包,元編程,運算符重載等等語法,這篇文章主要介紹了springboot中使用groovy的相關(guān)知識,需要的朋友可以參考下
    2022-09-09
  • Java基本知識點之變量和數(shù)據(jù)類型

    Java基本知識點之變量和數(shù)據(jù)類型

    這篇文章主要給大家介紹了關(guān)于Java基本知識點之變量和數(shù)據(jù)類型的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • 關(guān)于JavaEE內(nèi)部類的部分注意事項

    關(guān)于JavaEE內(nèi)部類的部分注意事項

    這篇文章主要介紹了關(guān)于JavaEE內(nèi)部類的部分注意事項,將一個類定義在另一個類里面或者一個方法里面,這樣的類稱為內(nèi)部類,這是一種封裝思想,那么使用內(nèi)部類的時候要注意些什么呢,讓我們一起來看看吧
    2023-03-03
  • SpringBoot之@Aspect注解解讀

    SpringBoot之@Aspect注解解讀

    這篇文章主要介紹了SpringBoot之@Aspect注解解讀,AOP是面向切面編程,通過預(yù)編譯方式和運行期動態(tài)代理實現(xiàn)程序功能的統(tǒng)一維護的一種技術(shù),而@Aspect 就是把一個類定義為切面供容器讀取,需要的朋友可以參考下
    2024-01-01
  • spring boot 監(jiān)控處理方案實例詳解

    spring boot 監(jiān)控處理方案實例詳解

    這篇文章主要介紹了spring boot 監(jiān)控處理方案的相關(guān)資料,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-07-07
  • java實現(xiàn)直線分形山脈

    java實現(xiàn)直線分形山脈

    這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)直線分形山脈,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • Spring Boot 如何整合連接池

    Spring Boot 如何整合連接池

    這篇文章主要介紹了Spring Boot 如何整合連接池,幫助大家更好的理解和學(xué)習(xí)spring boot框架,感興趣的朋友可以了解下
    2020-11-11
  • Java排序算法總結(jié)之歸并排序

    Java排序算法總結(jié)之歸并排序

    這篇文章主要介紹了Java排序算法總結(jié)之歸并排序,較為詳細(xì)的分析了歸并排序的原理與java實現(xiàn)技巧,需要的朋友可以參考下
    2015-05-05
  • springboot配置https安全連接的方法

    springboot配置https安全連接的方法

    這篇文章主要介紹了springboot配置https安全連接的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • 推薦一款I(lǐng)ntelliJ IDEA提示快捷鍵的Key Promoter X插件

    推薦一款I(lǐng)ntelliJ IDEA提示快捷鍵的Key Promoter X插件

    今天小編就為大家分享一篇關(guān)于IntelliJ IDEA提示快捷鍵的Key Promoter X插件,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-10-10

最新評論