`
xt_yangjie
  • 浏览: 39581 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

ibatis之旅

阅读更多
iBatis其实不是个真正意义上的OR-Mapping, 只能称为是个OSQL-Mapping吧,我们开发人员还是要自己写SQL,不过这个我比较喜欢,我们可以控制的更多,更灵活。不像Hibernate那么死板。
iBatis将Java对象(大多是我们的Java Bean)映射成JDBC的PreparedStatement的输入参数和ResultSet。个人认为主要就是将我的的Java对象映射到SQL的参数和将SQL的查询结果转换为Java对象。

下面说说我学习iBATIS SQL Maps开发指南的一些收获吧。

(1) SQL Map XML 配置文件 SqlMapConfig.xml的深刻认识。

<setting>元素,这个以前自己没有接触过,最学习到了,想和大家分享一下。<setting>元素用于配置和优化SqlMapClient实例。<setting>元素本身及其所有的属性都是可选的,子元素如下:

maxRequests 同时执行SQL语句的最大线程数,通常至少是maxTransactions的10倍,默认值是512。
maxSessions 同时活动的最大session数。应该小于maxRequests,并大于或等于maxTransactions,默认128。
maxTransactions 同时进入sqlMapClient.startTransaction()的最大线程数,默认32。
cacheModelsEnabled 全局性地启用或禁止SqlMapClient的所有缓存model,默认true。调试程序时使用。
lazyLoadingEnabled 全局性地启用或禁用SqlMapClient的所有延迟加载,默认true。调试程序时使用。
enhancementEnabled 全局性地启用或禁用运行时字节码增强,以优化访问Java Bean属性的性能,同时优化延迟加载的性能,默认false。

useStatementNamespaces 如果启用本属性,必须使用全限定名来引用 mapped statement。Mapped statement的全限定名由sql-map的名称和mapped-statement的名称组成,sql-map.mapped-statement。

(2) iBatis事务,可能用Spring AOP的声明式事务,我不用去管理iBatis的事务,交给Spring去管理了。但了解它还是不错的。<transactionManager>元素定义SQL MAP的事务管理服务。属性type指定所使用的事务管理器类型。
JDBC: 让JDBC管理事务,也就是使用通常的commit(), rollback()方法。
JTA: JTA本地事务管理器使用一个JTA全局事务。
EXTERNAL: 自己管理事务。

(3) 在SQL Map XML映射文件件中配置缓存,以前自己没接触这个,所以学习到了,感觉还是很兴奋地,呵呵。



<sqlMap id="Product">

            <cacheModel id="productCache" readOnly="true" type="LRU" serialize="false">  <!-之都缓存,采用LRU置换算法->

                <flushInterval hours="24"/>

                <flushOnExecute statement="insertProduct"/>

                <flushOnExecute statement="updateProduct"/>    <!-更新的时候刷新缓存->

                <flushOnExecute statement="deleteProduct"/>

                <property name="cache-size" value="1000"/>

            </cacheModel>
<!--利用缓存-->

            <staement id="getProductList" cacheModel="productCache" parameterClass="int">

                SELECT * FROM product WHERE prd_cat_id = #value#

            </statement>

        </sqlMap>



缓存分为制度缓存和读写缓存,读写缓存又分为Serializable可读写缓存和非Serializable可读写缓存,者两个还没弄打明白。
缓存类型分为:
MEMORY MEMORY cache实现使用reference类型来管理cache的行为。适于没有统一的对象重用模式的应用,或内存不足的到应用。
LRU LRU cache实现使用"近期最少使用"原则来确定如何从cache中清除对象。对于在较长的时期内,某些用户经常使用的某些特定对象的情况,LRU cache是个不错的选择。
FIFO FIFO cache实现使用"先进先出"的原则来确定如何从cache中清除对象。对于短时间内持续引用特定的查询而后很可能不再使用的情况,FIFO cache是个不错的选择。
OSCache 利用OSCache缓存插件。

(4) Parameter Map和Result Map
利用这两个Map我们可以控制更多的东西,利用nullValue我们可以指定NULL的替换值,这个对Java Bean的简单类型的属性很有用,但强烈要求Java Bean用类类型。

(5) 返回自动生成的主键
很多数据库支持自动生成主键的数据类型。不过这通常(并不总是)是个私有的特性。SQL Map 通过<insert>的子元素<selectKey>来支持自动生成的键值。
它同时支持预生成(如Oracle)和后生成两种类型(如 MySQL)。 下面是两个例子:<!



<!--Oracle SEQUENCE Example-->

<insert id="insertProduct-ORACLE" parameterClass="com.domain.Product">

<selectKey resultClass="int" keyProperty="id" >

SELECT STOCKIDSEQUENCE.NEXTVAL AS ID FROM DUAL

</selectKey>

insert into PRODUCT (PRD_ID,PRD_DESCRIPTION) values (#id#,#description#)

</insert>



(6) iBatis调用存储过程
SQL Map通过<procedure>元素支持存储过程。
下面给出调用存储过程的一个例子



<parameterMap id="swapParameters" class="map">

<parameter property="email1" jdbcType="VARCHAR" javaType="java.lang.String" mode="inout"/>

<parameter property="email2" jdbcType="VARCHAR" javaType="java.lang.String" mode="inout"/>

</parameterMap>


<procedure id="swapEmailAddress" parameterMap="swapParameters">

<![CDATA
{call swap_email_address(?,?)}
]>
</procedure>



注意!!!要确保始终只使用JDBC标准的存储过程语法。

(6) iBatis对象关联解决方案(复杂类型属性),同样可以实现Hibernate的对象关联。
第一种解决方案:
因为mapped statement知道如何装入合适的数据和Java类,通过将ResultMap的propery和相应的mapped statement联系起来,可以自动地给复杂类型的属性赋值。下面给出一个例子,Product和Category,一个Product属于一种Category,一种Category用多个Product。



<!-获得Product的Category->

<resultMap id="productResult" class="Product">

<result property="id" column="PRD_ID"/>

<result property="name" column="PRD_NAME"/>

<result property="category" column="PRD_CAT_ID" select="getCategory"/>           <!-HERE HERE HERE->

</resultMap>


<!-获得Category的ProductList->

<resultMap id="categoryResult" class="Category">

<result property="id" column="CAT_ID"/>

<result property="name" column="CAT_NAME"/>

<result property="productList" column="CAT_ID" select="getProductsByCatId"/>     <!-HERE HERE HERE->

</resultMap>








第二种解决方案:

联合查询

<!-获得Product的Category->

<resultMap id="productResult" class="Product">

<result property="id" column="PRD_ID"/>

<result property="name" column="PRD_NAME"/>

<result property="category.id" column="CAT_ID"/>

<result property="category.name" column="CAT_NAME"/>

</resultMap>

<select id="getProduct" parameterClass="int" resultMap="productResult">

SELECT PRD.PRD_ID, PRD.PRD_NAME, CAT.CAT_ID, CAT.CAT_NAME

FROM PRODUCT PRD,

CATEGORY CAT

WHERE PRD.PRD_ID = #value# AND PRD.CAT_ID = CAT.CAT_ID

</select>



好像Category的productList没法解决哦!!!

这两种方案的对比:
第一种方案总是执行2条SQL,但第二种方案要做表的join。选择的基本原则是如果需要经常访问关联对象,则使用联合查询(第二种方案),否则使用延迟加载和字节码增强选项的第一种方案。

(7) 动态SQL
相信大家都用过动态SQL,但我以前没用过iBatis的动态SQL,如今学到了感觉很好很强大,早知道就早点学习了,哈哈。

这些就是我最近学习iBatis的一些总结吧。



/**********************************************/

ibatis基础代码包括:
1.    ibatis实例配置
一个典型的配置文件如下(具体配置项目的含义见后):
<? xml version="1.0" encoding="UTF-8"    ?> 
<! DOCTYPE sqlMapConfig
      PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0/
      "http://www.ibatis.com/dtd/sql-map-config-2.dt

<sqlMapConfig > 

     < settings
       cacheModelsEnabled ="true"     
      enhancementEnabled ="true"     
      lazyLoadingEnabled ="true"     
      errorTracingEnabled ="true"     
      maxRequests ="32"          
      maxSessions ="10"          
      maxTransactions ="5"         
      useStatementNamespaces ="false"   
       /> 

     < transactionManager    type ="JDBC" > 

     < dataSource    type ="SIMPLE" > 
         < property    name ="JDBC.Driver"    value ="com.p6spy.engine.spy.P6SpyDriver" /> 
         < property    name ="JDBC.ConnectionURL"    value ="jdbc:mysql://localhost/sample" /> 
         < property    name ="JDBC.Username"    value ="user" /> 
         < property    name ="JDBC.Password"    value ="mypass" /> 
         < property    name ="Pool.MaximumActiveConnections"    value ="10" /> 
         < property    name ="Pool.MaximumIdleConnections"    value ="5" /> 
         < property    name ="Pool.MaximumCheckoutTime"    value ="120000" /> 
         < property    name ="Pool.TimeToWait"    value ="500" /> 
         < property    name ="Pool.PingQuery"    value ="select 1 from ACCOUNT" /> 
         < property    name ="Pool.PingEnabled"    value ="false" /> 
         < property    name ="Pool.PingConnectionsOlderThan"    value ="1" /> 
         < property    name ="Pool.PingConnectionsNotUsedFor"    value ="1" /> 
       </ dataSource > 
     </ transactionManager > 

     < sqlMap    resource ="com/ibatis/sample/User.xml" /> 

</ sqlMapConfig >  
 

⑴ Settings 节点

cacheModelsEnabled 
是否启用SqlMapClient上的缓存机制。 建议设为"true"

enhancementEnabled 
是否针对POJO启用字节码增强机getter/setter的调用效能,避免Reflect所带来的性能开销。同时,这也为Lazy Loading带来提升。 建议设为"true"

errorTracingEnabled
是否启用错误日志,在开发期间建议设为"true" 以方便调试

lazyLoadingEnabled
是否启用延迟加载机制,建议设为"true"

maxRequests
最大并发请求数(Statement并发数)

maxTransactions 
最大并发事务数

maxSessions    最大Session数。即当前最大允许的并发SqlMapClient数。

useStatementNamespaces 
是否使用Statement命名空间。
这里的命名空间指的是映射文件中,sqlMap节的namespace属性,如在上例中针对t_use
表的映射文件sqlMap节点: <sqlMap namespace="User"> 这里,指定了此sqlMap节点下定义的操作均属于"User"命名空间。 在useStatementNamespaces="true"的情况下,Statement调用需追加命名空间,如:sqlMap.update("User.updateUser",user);
否则直接通过Statement名称调用即可,如: sqlMap.update("updateUser",user); 但请注意此时需要保证所有映射文件中,Statement定义无重名。


transactionManager节点
transactionManager节点定义了ibatis的事务管理器,目前提供了以下几种选择:
JDBC
通过传统JDBC Connection.commit/rollback实现事务支持。 
JTA
使用容器提供的JTA服务实现全局事务管理。
EXTERNAL
外部事务管理,如在EJB中使用ibatis,通过EJB的部署配置即可实现自
动的事务管理机制。此时ibatis将把所有事务委托给外部容器进行管理。

dataSource节点
    dataSource从属于transactionManager节点,用于设定ibatis运行期使用的DataSource属性。
type属性:
dataSource节点的type属性指定了dataSource的实现类型。 可选项目:
SIMPLE:
    SIMPLE是ibatis内置的dataSource实现,其中实现了一个简单的
数据库连接池机制,对应 ibatis 实现类为
com.ibatis.sqlmap.engine.datasource.SimpleDataSourceFactory。

DBCP:
    基于Apache DBCP连接池组件实现的DataSource封装,当无容器提
供DataSource服务时,建议使用该选项,对应ibatis实现类为
com.ibatis.sqlmap.engine.datasource.DbcpDataSourceFactory。

JNDI:
使用J2EE容器提供的DataSource实现,DataSource将通过指定
的JNDI Name从容器中获取。对应 ibatis实现类为
com.ibatis.sqlmap.engine.datasource.JndiDataSourceFactory。

dataSource的子节点说明(SIMPLE&DBCP):
JDBC.Driver    JDBC 驱动。
如:org.gjt.mm.mysql.Driver

JDBC.ConnectionURL 
数据库URL。
如:jdbc:mysql://localhost/sample
如果用的是SQLServer JDBC Driver,需要
在url后追加SelectMethod=Cursor以获得
JDBC事务的多Statement支持。
JDBC.Username
    数据库用户名
JDBC.Password 
数据库用户密码
Pool.MaximumActiveConnections
数据库连接池可维持的最大容量。

Pool.MaximumIdleConnections
数据库连接池中允许的挂起(idle)连接数。

JNDI由于大部分配置是在应用服务器中进行,因此ibatis中的配置相对简
分别使用JDBC和JTA事务管理的JDNI配置:
使用JDBC事务管理的JNDI DataSource配置


< transactionManager    type ="JDBC"     > 
< dataSource    type ="JNDI" > 
< property    name ="DataSource"     value ="java:comp/env/jdbc/myDataSource" /> 
</ dataSource > 
</ transactionManager > 
< transactionManager    type ="JTA"     > 
< property    name ="UserTransaction"     value ="java:/ctx/con/UserTransaction" /> 
< dataSource    type ="JNDI" > 
< property    name ="DataSource"     value ="java:comp/env/jdbc/myDataSource" /> 
</ dataSource >  
sqlMap节点
sqlMap节点指定了映射文件的位置,配置中可出现多个sqlMap节点,以指定
项目内所包含的所有映射文件。

ibatis基础语义

XmlSqlMapClientBuilder
XmlSqlMapClientBuilder是ibatis 2.0之后版本新引入的组件,用以替代1.x
版本中的XmlSqlMapBuilder。其作用是根据配置文件创建SqlMapClient实例。

SqlMapClient
SqlMapClient是ibatis的核心组件,提供数据操作的基础平台。SqlMapClient
可通过XmlSqlMapClientBuilder创建:
 

String resource    = " com/ibatis/sample/SqlMapConfig.xml " ;
Reader reader;

reader    =    Resources.getResourceAsReader(resource);

XmlSqlMapClientBuilder xmlBuilder    =  
new    XmlSqlMapClientBuilder();

SqlMapClient sqlMap    =    xmlBuilder.buildSqlMap(reader); 
"com/ibatis/sample/SqlMapConfig.xml"指明了配置文件在CLASSPATH
中的相对路径。XmlSqlMapClientBuilder通过接受一个Reader类型的配置文
件句柄,根据配置参数,创建SqlMapClient实例。

SqlMapClient提供了众多数据操作方法,下面是一些常用方法的示例,具体说明
文档请参见ibatis java doc,或者ibatis官方开发手册。

SqlMapClient基本操作示例

以下示例摘自ibatis官方开发手册,笔者对其进行了重新排版以获得更好的阅读效果。
例1: 数据写入操作(insert, update, delete):


sqlMap.startTransaction();
Product product    =     new    Product();
product.setId ( 1 );
product.setDescription (“Shih Tzu”);
int    rows    =    sqlMap.insert (“insertProduct”, product);
sqlMap.commitTransaction(); 
例2: 数据查询 (select)


sqlMap.startTransaction();
Integer key    =     new    Integer ( 1 );
Product product    =    (Product)sqlMap.queryForObject (“getProduct”, key);
sqlMap.commitTransaction(); 
例3: 在指定对象中存放查询结果(select) 


sqlMap.startTransaction();
Customer customer    =     new    Customer();
sqlMap.queryForObject(“getCust”, parameterObject, customer);
sqlMap.queryForObject(“getAddr”, parameterObject, customer);
sqlMap.commitTransaction(); 
例4: 执行批量查询 (select)


sqlMap.startTransaction();
List list    =    sqlMap.queryForList (“getProductList”,    null )
sqlMap.commitTransaction(); 
例5: 关于AutoCommit


// 没有预先执行startTransaction时,默认为auto_commit模式 
int    rows    =    sqlMap.insert (“insertProduct”, product); 
例6:查询指定范围内的数据


sqlMap.startTransaction();
List list    =    sqlMap.queryForList (“getProductList”,    null ,    0 ,    40 );
sqlMap.commitTransaction(); 
例7: 结合RowHandler进行查询(select)


    public     class    MyRowHandler    implements    RowHandler     {
      public     void    handleRow (Object object, List list)    throws 
      SQLException     {
        Product product    =    (Product) object;
        product.setQuantity ( 10000 );
        sqlMap.update (“updateProduct”, product);
      } 

sqlMap.startTransaction();
RowHandler rowHandler    =     new    MyRowHandler();
List list    =    sqlMap.queryForList (“getProductList”,    null ,
rowHandler);
sqlMap.commitTransaction(); 
 

// 例8: 分页查询 (select) 
PaginatedList list    = 
sqlMap.queryForPaginatedList (“getProductList”,    null ,    10 );
list.nextPage();
list.previousPage();


// 例9: 基于Map的批量查询 (select) 
sqlMap.startTransaction();
Map map    =    sqlMap.queryForMap (“getProductList”,    null , “productCode”);
sqlMap.commitTransaction();
Product p    =    (Product) map.get(“EST - 93 ”); 


/************************************************************************/
主要是sqlMapConfig.xml:
<?xml version="1.0" encoding="UTF-8" ?>
  <!DOCTYPE sqlMapConfig (View Source for full doctype...)>
- <sqlMapConfig>
- <!--  Configure a built-in transaction manager.  If you're using an
       app server, you probably want to use its transaction manager
       and a managed datasource
  -->
- <transactionManager type="JDBC" commitRequired="false">
- <dataSource type="SIMPLE">
  <property name="JDBC.Driver" value="org.hsqldb.jdbcDriver" />
  <property name="JDBC.ConnectionURL" value="jdbc:hsqldb:." />
  <property name="JDBC.Username" value="sa" />
  <property name="JDBC.Password" value="sa" />
  </dataSource>
  </transactionManager>
- <!--  List the SQL Map XML files. They can be loaded from the
       classpath, as they are here (com.domain.data...)
  -->
  <sqlMap resource="com/mydomain/data/Account.xml" />
- <!--  List more here...
  <sqlMap resource="com/mydomain/data/Order.xml"/>
  <sqlMap resource="com/mydomain/data/Documents.xml"/>
 
  -->
  </sqlMapConfig>
以及sql的映射问价,如Account.xml的文件内容:
<?xml version="1.0" encoding="UTF-8" ?>
  <!DOCTYPE sqlMap (View Source for full doctype...)>
- <sqlMap namespace="Account">
- <!--  Use type aliases to avoid typing the full classname every time.
  -->
  <typeAlias alias="Account" type="com.mydomain.domain.Account" />
- <!--  Result maps describe the mapping between the columns returned
       from a query, and the class properties.  A result map isn't
       necessary if the columns (or aliases) match to the properties
       exactly.
  -->
- <resultMap id="AccountResult" class="Account">
  <result property="id" column="ACC_ID" />
  <result property="firstName" column="ACC_FIRST_NAME" />
  <result property="lastName" column="ACC_LAST_NAME" />
  <result property="emailAddress" column="ACC_EMAIL" />
  </resultMap>
- <!--  Select with no parameters using the result map for Account class.
  -->
  <select id="selectAllAccounts" resultMap="AccountResult">select * from ACCOUNT</select>
- <!--  A simpler select example without the result map.  Note the
       aliases to match the properties of the target result class.
  -->
  <select id="selectAccountById" parameterClass="int" resultClass="Account">select ACC_ID as id, ACC_FIRST_NAME as firstName, ACC_LAST_NAME as lastName, ACC_EMAIL as emailAddress from ACCOUNT where ACC_ID = #id#</select>
- <!--  Insert example, using the Account parameter class
  -->
  <insert id="insertAccount" parameterClass="Account">insert into ACCOUNT ( ACC_ID, ACC_FIRST_NAME, ACC_LAST_NAME, ACC_EMAIL values ( #id#, #firstName#, #lastName#, #emailAddress# )</insert>
- <!--  Update example, using the Account parameter class
  -->
  <update id="updateAccount" parameterClass="Account">update ACCOUNT set ACC_FIRST_NAME = #firstName#, ACC_LAST_NAME = #lastName#, ACC_EMAIL = #emailAddress# where ACC_ID = #id#</update>
- <!--  Delete example, using an integer as the parameter class
  -->
  <delete id="deleteAccountById" parameterClass="int">delete from ACCOUNT where ACC_ID = #id#</delete>
  </sqlMap>



上网看到的一篇关于ibatis的文章,感觉不错,就给记下来了。
地址:http://archive.cnblogs.com/a/2041765/
分享到:
评论

相关推荐

    java+ibatis实例教程

    Java+MyBatis 实例教程 Java 和 MyBatis 是两个在软件开发中广泛应用的技术,尤其是在构建企业级 Web 应用程序时。Java 是一种面向对象的编程语言,以其跨平台性和强大...祝你在 Java+MyBatis 的学习之旅中收获满满!

    强烈推荐的 iBATIS 书籍

    iBATIS 是一款著名的开源Java持久层框架,它在2005年由Mike...对于那些热衷于源码分析和工具研究的标签爱好者,这本书将是一次深度探索之旅,帮助他们深入理解iBATIS 的内部工作原理,并提升其在Java开发中的技能水平。

    ibatis in action

    《iBATIS in Action》是一本专注于iBATIS框架的英文版专著,它为读者提供了一条深入了解...而压缩包内的"IBATIS in Action - Manning.pdf"正是这本书的电子版,它将带你走进iBATIS的世界,开启你的持久层框架学习之旅。

    淘宝实习笔记--webx学习之旅

    【淘宝实习笔记--webx学习之旅】这篇笔记主要记录了作者在淘宝实习期间关于Webx框架的学习和理解。Webx是一个用于构建企业级Web应用程序的框架,它在淘宝内部广泛使用。以下是一些核心知识点: 1. **iBATIS**:...

    一个程序员的自省(博客园)--超级推荐

    作者通过自己的F#探险之旅,整理了相关教程,帮助初学者快速入门,并对比了F#与C#的差异,强调了函数式编程的优势。 【Visual Studio插件增强开发体验】 Visual Studio的插件生态系统极大地丰富了IDE的功能,使...

    Spring in Action(第2版)中文版

    第1章开始spring之旅 1.1spring是什么 1.2开始spring之旅 1.3理解依赖注入 1.3.1依赖注入 1.3.2di应用 1.3.3企业级应用中的依赖注入 1.4应用aop 1.4.1aop介绍 1.4.2aop使用 1.5小结 第2章基本bean装配 ...

    Spring in Action(第二版 中文高清版).part2

    第1章 开始Spring之旅 1.1 Spring是什么 1.2 开始Spring之旅 1.3 理解依赖注入 1.3.1 依赖注入 1.3.2 DI应用 1.3.3 企业级应用中的依赖注入 1.4 应用AOP 1.4.1 AOP介绍 1.4.2 AOP使用 1.5 小结 第2章 ...

    Spring in Action(第二版 中文高清版).part1

    第1章 开始Spring之旅 1.1 Spring是什么 1.2 开始Spring之旅 1.3 理解依赖注入 1.3.1 依赖注入 1.3.2 DI应用 1.3.3 企业级应用中的依赖注入 1.4 应用AOP 1.4.1 AOP介绍 1.4.2 AOP使用 1.5 小结 第2章 ...

    通向架构师的道路.rar

    6. **通向架构师的道路(第二十四天)之Oracle性能调优-朝拜先知之旅.docx** Oracle是广泛使用的数据库系统,性能调优是提升数据库效率的关键。文档可能涵盖了索引优化、查询优化、存储结构调整等方法,帮助读者深入...

    Mybatis-Spring1.0.2中文版说明文档

    ### 章节二:开始 Mybatis-Spring 之旅 这部分可能涉及如何设置项目,配置Spring和Mybatis的集成,以及如何创建和管理SqlSession和Mapper接口。 ### 章节三:SqlSessionFactoryBean SqlSessionFactoryBean是...

    spring in action英文版

    例如,第1章“开始Spring之旅”介绍了使用Spring的原因,包括J2EE开发者的日常工作以及Spring提供的承诺。此外,Spring的反向控制(IoC)和面向切面编程(AOP)是Spring框架的核心特性,而这一部分也详细解释了如何...

    Flex技术入门之如何创建flex的web工程

    【Flex技术入门:创建Web工程详解】 Flex技术是Adobe公司为了解决Flash开发难题而推出的一种专门面向程序开发人员的...在开始Flex开发之旅之前,了解其优缺点和创建Web工程的基本流程,将有助于你更好地掌握这项技术。

    SpringBoot整合Mybatis初学者,简单实用

    在IT行业中,SpringBoot和Mybatis是两个非常流行的框架,它们分别用于简化Spring应用的开发和处理数据库操作。本文将详细介绍如何将这两个框架...希望这个简明教程能对初学者有所帮助,开启愉快的Java Web开发之旅。

    技术分享之Web服务后台开发框架升级:从SpringMVC+Hibernate到SpringBoot+Mybatis

    MyBatis是一个优秀的持久层框架,其前身是Apache的iBatis项目。它允许开发者以声明式的方式处理SQL查询,并支持存储过程和高级映射。以下是MyBatis的关键特性: - **最新版本**:...

Global site tag (gtag.js) - Google Analytics