`
maosheng
  • 浏览: 554359 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

iBATIS 框架之系统架构与映射原理

    博客分类:
  • ORM
orm 
阅读更多
简介:
iBATIS 通过 SQL Map 将 Java 对象映射成 SQL 语句和将结果集再转化成 Java 对象,与其他 ORM 框架相比,既解决了 Java 对象与输入参数和结果集的映射,又能够让用户方便的手写使用 SQL 语句。
本文主要介绍了 iBATIS 框架的体系结构和运行流程,以及 iBATIS 如何完成 SQL 语句的解析与 Java 对象与数据字段映射关系的建立,最后用一个实例说明了 iBATIS 是如何帮我们完成工作的。

iBATIS 框架主要的类层次结构:
总体来说 iBATIS 的系统结构还是比较简单的,它主要完成两件事情:
1.根据 JDBC 规范建立与数据库的连接;
2.通过反射打通 Java 对象与数据库参数交互之间相互转化关系。

iBATIS 的框架结构也是按照这种思想来组织类层次结构的,其实它是一种典型的交互式框架。先期准备好交互的必要条件,然后构建一个交互的环境,交互环境中还划分成会话,每次的会话也有一个环境。当这些环境都准备好了以后,剩下的就是交换数据了。其实涉及到网络通信,一般都会是类似的处理方式。
图 1 是 iBATIS 框架的主要的类层次结构图:



上面的类图中左边 SqlMapClient 接口主要定义了客户端的操作行为包括 select、insert、update、delete。而右边主要是定义了当前客户端在当前线程的执行环境。SqlMapSession 可以共享使用,也可以自己创建,如果是自己创建在结束时必须要调用关闭接口关闭。
当使用者持有了 SqlMapClientImpl 对象就可以使用 iBATIS 来工作了。这里还要提到另外一个类 SqlMapExecutorDelegate 这个类从名字就可以看出他是执行代理类。这个类非常重要,重要是因为他耦合了用户端的执行操作行为和执行的环境,他持有执行操作的所需要的数据,同时提供管理着执行操作依赖的环境。所以他是一个强耦合的类,也可以看做是个工具类。

iBATIS 框架的设计策略:
iBATIS 主要的设计目的还是为了让我们执行 SQL 时对输入输出的数据管理更加方便,所以如何方便的让我们写出 SQL 和方便的获取 SQL 的执行结果才是 iBATIS 的核心竞争力。那么 iBATIS 是怎么实现它的核心竞争力的呢?
iBATIS 框架的一个重要组成部分就是其 SqlMap 配置文件,SqlMap 配置文件的核心是 Statement 语句包括 CIUD。 iBATIS 通过解析 SqlMap 配置文件得到所有的 Statement 执行语句,同时会形成 ParameterMap、ResultMap 两个对象用于处理参数和经过解析后交给数据库处理的 Sql 对象。这样除去数据库的连接,一条 SQL 的执行条件已经具备了。
图 2 描述了 Statement 有关的类结构图:




图 2 给出了围绕 SQL 执行的基本的结构关系,但是还有一个关键的部分就是,如何定义 SQL 语句中的参数与 Java 对象之间的关系,这其中还涉及到 Java 类型到数据库类型的转换等一系列问题。

数据的映射大体的过程是这样的:根据 Statement 中定义的 SQL 语句,解析出其中的参数,按照其出现的顺序保存在 Map 集合中,并按照 Statement 中定义的 ParameterMap 对象类型解析出参数的 Java 数据类型。并根据其数据类型构建 TypeHandler 对象,参数值的复制是通过 DataExchange 对象完成的。
图 3 是参数映射相关的类结构图:



图 3 是输入参数的映射结构情况,返回结果 ResultMap 的映射情况也是类似的。主要就是要解决 SQL 语句中的参数与返回结果的列名与 Statement 中定义的 parameterClass 和 resultClass 中属性的对应关系。

iBATIS 框架的运行原理:
前面大体分析了 iBATIS 框架的主要类的结构,这里主要看一下这些类是如何串联起来、如何工作的。
图 4 描述了整个过程的主要执行步骤。




上图中描述的 SqlMapSession 对象的创建和释放根据不同情况会有不同,因为 SqlMapSession 负责创建数据库的连接,包括对事务的管理,iBATIS 对管理事务既可以自己管理也可以由外部管理,iBATIS 自己管理是通过共享 SqlMapSession 对象实现的,多个 Statement 的执行时共享一个 SqlMapSession 实例,而且都是线程安全的。如果是外部程序管理就要自己控制 SqlMapSession 对象的生命周期。

代码示例:
下面我们将根据一个具体的实例解析一个 Statement 如何完成映射的,我们用一个典型的查询语句看看 Java 对象中的数据时如何赋给 SQL 中的参数的,再看看 SQL 的查询结果是如何转成 Java 对象的。

Spring 的 applicationContext 配置文件(applicationContext.xml):

<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
    <bean id="sqlMapTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <bean id="sqlMapTransactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
        <property name="transactionManager" ref="sqlMapTransactionManager"/>
    </bean>
    <!--sql map -->
    <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
        <property name="configLocation" value="com/mydomain/data/SqlMapConfig.xml"/>
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <bean id="dataSource" name="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
        <property name="url" value="jdbc:oracle:thin:@10.1.5.11:1521:XE"/>
        <property name="username" value="junshan"/>
        <property name="password" value="junshan"/>
        <property name="maxActive" value="20"/>
    </bean>
    <bean id="accountDAO" class="com.mydomain.DAO.AccountDAO">
        <property name="sqlMapClient" ref="sqlMapClient"/>
        <property name="sqlMapTransactionTemplate" ref="sqlMapTransactionTemplate"/>
    </bean>
</beans>

iBatis的SqlMapConfig配置文件(SqlMapConfig.xml)
<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE sqlMapConfig     
    PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"     
    "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">

<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="oracle.jdbc.driver.OracleDriver"/>
      <property name="JDBC.ConnectionURL" value="jdbc:oracle:thin:@10.1.5.11:1521:XE"/>
      <property name="JDBC.Username" value="junshan"/>
      <property name="JDBC.Password" value="junshan"/>
      <property name="JDBC.DefaultAutoCommit" value="true"></property>
    </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>

Account.xml配置文件
<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE sqlMap     
    PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"     
    "http://ibatis.apache.org/dtd/sql-map-2.dtd">

<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" nullValue="0"/>
    <result property="firstName" column="ACC_FIRST_NAME"/>
    <result property="lastName" column="ACC_LAST_NAME"/>
    <result property="emailAddress" column="ACC_EMAIL"/>
    <result property="date" column="ACC_DATE"/>
  </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="selectAccount" parameterClass="Account" resultClass="Account">
    select
      ACC_ID,
      ACC_FIRST_NAME as firstName,
      ACC_LAST_NAME as lastName,
      ACC_EMAIL as emailAddress,
      ACC_DATE
    from ACCOUNT
    where ACC_ID = #id:INTEGER# and ACC_FIRST_NAME = #firstName#
  </select>


  <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,
      ACC_DATE as date
    from ACCOUNT
    where ACC_ID = #id:INTEGER# and ACC_FIRST_NAME = #firstName#
  </select>
  <!-- Insert example, using the Account parameter class -->
  <insert id="insertAccount" parameterClass="Account">
    insert into ACCOUNT (
      ACC_FIRST_NAME,
      ACC_LAST_NAME,
      ACC_EMAIL,
        ACC_ID,
        ACC_DATE)
    values (
      #firstName#, #lastName:VARCHAR#, #emailAddress#, #id#, #date:DATE#
    )
  </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>

Java 测试类:

package com.mydomain.domain;

import java.util.Date;

public class Account {

  private int id;
  private String firstName;
  private String lastName;
  private String emailAddress;
  private Date date;

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public int getId() {
    return id;
  }

  public void setId(int id) {
    this.id = id;
  }

  public String getFirstName() {
    return firstName;
  }

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }

  public String getLastName() {
    return lastName;
  }

  public void setLastName(String lastName) {
    this.lastName = lastName;
  }

  public String getEmailAddress() {
    return emailAddress;
  }

  public void setEmailAddress(String emailAddress) {
    this.emailAddress = emailAddress;
  }

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", firstName='" + firstName + '\'' +
                ", lastName='" + lastName + '\'' +
                ", emailAddress='" + emailAddress + '\'' +
                '}';
    }
}


package com.mydomain.dao;

import com.mydomain.domain.Account;
import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;
import org.springframework.transaction.support.TransactionTemplate;

import java.sql.SQLException;
import java.util.List;

/**
*
* To change this template use File | Settings | File Templates.
*/
public class AccountDAO extends SqlMapClientDaoSupport {
    /**
*  数据库的事务模板
*/
protected TransactionTemplate sqlMapTransactionTemplate;

    public TransactionTemplate getSqlMapTransactionTemplate() {
return sqlMapTransactionTemplate;
}

public void setSqlMapTransactionTemplate(TransactionTemplate sqlMapTransactionTemplate) {
this.sqlMapTransactionTemplate = sqlMapTransactionTemplate;
}
  public List selectAll(){
        return getSqlMapClientTemplate().queryForList("selectAllAccounts");
  }
  public  Account selectAccountById  (int id) throws SQLException {
    return (Account) getSqlMapClientTemplate().queryForObject("selectAccountById", id);
  }

  public  Account selectAccount  (Account account) throws SQLException {
    return (Account) getSqlMapClientTemplate().queryForObject("selectAccount", account);
  }
  public  void insertAccount (Account account) throws SQLException {
    getSqlMapClientTemplate().insert("insertAccount", account);
  }

  public  void updateAccount (Account account) throws SQLException {
    getSqlMapClientTemplate().update("updateAccount", account);
  }

  public  void deleteAccount (int id) throws SQLException {
    getSqlMapClientTemplate().delete("deleteAccountById", id);
  }

}


package com.mydomain.test;

import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;
import com.ibatis.common.resources.Resources;
import com.mydomain.domain.Account;

import java.io.Reader;
import java.io.IOException;
import java.util.List;
import java.sql.SQLException;

/**
* This is not a best practices class.  It's just an example
* to give you an idea of how iBATIS works.  For a more complete
* example, see JPetStore 5.0 at http://www.ibatis.com.
*/
public class SimpleExample {

  /**
   * SqlMapClient instances are thread safe, so you only need one.
   * In this case, we'll use a static singleton.  So sue me.  ;-)
   */
  private static SqlMapClient sqlMapper;

  /**
   * It's not a good idea to put code that can fail in a class initializer,
   * but for sake of argument, here's how you configure an SQL Map.
   */
  static {
    try {
      Reader reader = Resources.getResourceAsReader("com/mydomain/data/SqlMapConfig.xml");
      sqlMapper = SqlMapClientBuilder.buildSqlMapClient(reader);
      reader.close();
    } catch (IOException e) {
      // Fail fast.
      throw new RuntimeException("Something bad happened while building the SqlMapClient instance." + e, e);
    }
  }

  public static List selectAllAccounts () throws SQLException {
    return sqlMapper.queryForList("selectAllAccounts");
  }

  public static Account selectAccountById  (int id) throws SQLException {
    return (Account) sqlMapper.queryForObject("selectAccountById", id);
  }
public static Account selectAccount (Account account) throws SQLException {
    return (Account) sqlMapper.queryForObject("selectAccount", account);
  }
  public static void insertAccount (Account account) throws SQLException {
    sqlMapper.insert("insertAccount", account);
  }

  public static void updateAccount (Account account) throws SQLException {
    sqlMapper.update("updateAccount", account);
  }

  public static void deleteAccount (int id) throws SQLException {
    sqlMapper.delete("deleteAccountById", id);
  }
  public SqlMapClient getSqlMapClient(){
      return sqlMapper;
  }
   
  public static void main(String[] args) throws Exception{
        SimpleExample accountDAO = new SimpleExample();
        Account account = new Account();
        account.setId(1);
        account.setFirstName("tao");
        account.setLastName("bao");
        //account.setEmailAddress("junshan@taobao.com");
        try {
            SqlMapClient sqlMapper = accountDAO.getSqlMapClient();
            //sqlMapper.startTransaction();
             //accountDAO.deleteAccount(account.getId());
             accountDAO.insertAccount(account);
             account = accountDAO.selectAccount(account);
             System.out.println(account);
             account.setFirstName("bobo");
             accountDAO.updateAccount(account);
             System.out.println(account);
             //accountDAO.insertAccount(account);
            //sqlMapper.commitTransaction();
             List as = accountDAO.selectAllAccounts();

         } catch (SQLException e) {
             e.printStackTrace();
         }
  }
}


package com.mydomain.test;

import java.util.Date;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;

import com.mydomain.DAO.AccountDAO;
import com.mydomain.domain.Account;


public class SimpleTest {
     public static void main(String[] args) {
        ApplicationContext factory = new ClassPathXmlApplicationContext("/com/mydomain/data/applicationContext.xml");
        final AccountDAO accountDAO = (AccountDAO) factory.getBean("accountDAO");
        final Account account = new Account();
        account.setId(1);
        account.setFirstName("tao");
        account.setLastName("bao");
        account.setEmailAddress("junshan@taobao.com");
        account.setDate(new Date());
        try {
            accountDAO.getSqlMapTransactionTemplate().execute(new TransactionCallback(){
                    public Object doInTransaction(TransactionStatus status){
                        try{
                            accountDAO.deleteAccount(account.getId());
                            accountDAO.insertAccount(account);
                            account.setLastName("bobo");
                            accountDAO.updateAccount(account);
                            Account result = accountDAO.selectAccount(account);
                            System.out.println(result);
                            return null;
                        } catch (Exception e) {
                            status.setRollbackOnly();
                            return false;
                        }
                    }
                });
            //accountDAO.getSqlMapClient().commitTransaction();
        } catch (Exception e) {
             e.printStackTrace();
        }
     }

}

当我们执行:
accountDAO.selectAccount(account);
解析后的 SQL:
select
    ACC_ID,
    ACC_FIRST_NAME as firstName,
    ACC_LAST_NAME as lastName,
    ACC_EMAIL as emailAddress,
    ACC_DATE
from ACCOUNT
where ACC_ID = ? and ACC_FIRST_NAME = ?

iBATIS 将会选择Account.xml中这条 Statement 来解析,最终会把它解析成一个标准的 SQL 提交给数据库执行,并且会设置两个选择条件参数。
iBATIS 会把 SqlMap 配置文件解析成一个个 Statement,其中包括 ParameterMap、ResultMap,以及解析后的 SQL。当 iBATIS 构建好 RequestScope 执行环境后,要做的工作就是把传过来的对象数据结合 ParameterMap 中信息提取出一个参数数组,这个数组的顺序就是对应于 SQL 中参数的顺序,然后会调用 preparedStatement.setXXX(i, parameter) 提交参数。

#id# 将被解析成 Account 对象的 id 属性。#firstName# 同样被解析成 Account 对象的 firstName 属性,而 parameterClass="Account"指明了 Account 的类类型。接着 iBATIS 会根据这些变量和 parameterClass 指定的类型创建合适的 dataExchange 和 parameterPlan 对象。parameterPlan 对象中按照前面的顺序保存了变量的setter 和 getter 方法列表。
映射参数值到数据库过程时序图



映射返回对象时序图



配置文件与相应代码对应关系图



iBATIS 要达到目的就是把用户关心的和容易变化的数据放到配置文件中配置,方便用户管理。而把流程性的、固定不变的交给 iBATIS 来实现。这样是用户操作数据库简单、方便,这也是 iBATIS 的价值所在。
  • 大小: 12.7 KB
  • 大小: 31 KB
  • 大小: 23.2 KB
  • 大小: 17.4 KB
  • 大小: 67 KB
  • 大小: 58 KB
  • 大小: 33.1 KB
分享到:
评论

相关推荐

    深入分析 iBATIS 框架之系统架构与映射原理

    深入分析 iBATIS 框架之系统架构与映射原理深入分析 iBATIS 框架之系统架构与映射原理深入分析 iBATIS 框架之系统架构与映射原理深入分析 iBATIS 框架之系统架构与映射原理

    iBatis框架搭建用到的所有jar包

    纵观目前主流的 ORM(对象关系映射),无论 Hibernate还是Apache OJB,都对数据库结构提供了较为完整的封装,提供了从POJO到数据库表的全套映射机制。程序员往往只需定义好了POJO 到数据库表的映射关系,即可通过 ...

    iBATIS实战

    本书是讲述iBATIS框架的权威著作。书中既详实地介绍了iBATIS的设计理念和基础知识,也讨论了动态SQL、高速缓存、DAD框架等高级主题,还讲解了iBATIS在实际开发中的应用。书的最后给出了一个设计优雅、层次清晰的示例...

    各技术框架架构图.doc

    各技术框架架构图 Spring 框架架构图: Spring 框架是一种开源框架,主要用于解决企业应用程序开发的复杂性。其核心优势在于分层架构,允许开发者选择使用哪些组件,同时提供了集成的框架 для J2EE 应用程序...

    快速开发框架, SSM 架构 mybatis-plus kisso 实战项目.rar

    iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs) MyBatis 是⼀款优秀的持久层框架,它⽀持定制化 SQL、存储过程以及⾼级映射。MyBatis 避免了⼏乎所有的 JDBC 代码和⼿动设置参数以及获取结果集。...

    六大类系统架构图及其简介分享.pdf

    3. iBATIS 框架架构图 iBATIS 是一个基于 Java 的持久层框架。iBATIS 提供的持久层框架包括 SQL Maps 和 Data Access Objects(DAO),同时还提供一个利用这个框架开发的 JPetStore 实例。iBATIS 的最大优点是可以...

    各种系统架构图及其简介.pdf

    其主要优势之一是分层架构,允许开发者选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。Spring 框架的功能可以用在任何 J2EE 服务器中,大多数功能也适用于不受管理的环境。 Spring 框架的核心要点是...

    六大类系统架构图及其简介.doc

    框架的主要优势之一就是其分层架构,分层架构允许您选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。Spring 框架的功能可以用在任何 J2EE 服务器中,大多数功能也适用于不受管理的环境。 Spring 的...

    通用管理框架正式版1.1源码

    关系数据库与对象的映射,将SQL逻辑放到外部的XML配置文件中,以方便以后的维护。 这个框架有两个主要的组成部分,一个是SQL Maps,另一个是 Data Access Objects。Sql Maps是这个框架的核心部分,通过使用Sql Maps...

    AppFuse学习笔记(J2EE入门级框架)

    Appfuse是Matt Raible 开发的一个指导性的入门级J2EE框架,它对如何集成流行的Spring、Hibernate、iBatis、Struts、xDcolet、Junit、Taperstry、JSF等基础框架给出了示范。在持久层,AppFuse采用了Hibernate O/R映射...

    基于maven项目的SSM框架与layu前端框架的代码

    iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO)MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。MyBatis使用简单的XML或注解用于配置和原始映射,将接口和Java的POJOs(Plain ...

    Java软件开发工程师面试题宝典.pdf

    本资源提供了Java软件开发工程师面试的重要知识点,涵盖了Java基础知识、J2EE规范、Spring和iBatis框架、多线程、Linux命令操作、设计模式、数据库操作等多方面的内容,为Java开发工程师提供了一个系统的知识架构。

    Mybatis学习笔记整合架构

    Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql...,最后由mybatis框架执行sql并将结果映射成java对象并返回...

    SSH框架部分常见面试题.pdf

    常见的 ORM 框架还有 TopLink、iBatis 等。 DB、DBMS、DBA DB 是数据库,DBMS 是数据库管理系统,DBA 是数据库管理员。 ORM ORM 是对象关系映射,用于将 Java 对象转换到数据库表中。 主键和索引 主键是唯一...

    40道MyBatis面试题带答案(很全)

    MyBatis是一款优秀的持久层框架,用于支持普通SQL查询、存储过程和高级映射。它消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。 MyBatis前身叫iBatis,本是Apache的一个开源项目,2010年由apache ...

    MyStudentManagerSSM-1.0.zip

    基于java的学生管理系统,需要的小伙伴支持下载; 亲,一定能用! SSM框架——详细整合教程(Spring+SpringMVC+MyBatis) 最近在学习Spring+SpringMVC+MyBatis的整合。以下是参考网上的资料自己实践操作的...

    Appfuse开发教程

    Appfuse是Matt Raible 开发的一个指导性的入门级J2EE框架,它继承了流行的Spring、Hibernate、ibatis、struts、Xdcolet、junit等基础框架,最新的1.7版更是提供了对Taperstry和JSF的支持。在持久层,AppFuse采用了...

    appfuse 学习笔记

    Appfuse是Matt Raible 开发的一个指导性的入门级J2EE框架,它对如何集成流行的Spring、Hibernate、iBatis、Struts、xDcolet、Junit、Taperstry、JSF等基础框架给出了示范。在持久层,AppFuse采用了Hibernate O/R映射...

    计算机专业个人简历-(1).doc

    * 了解ibatis框架 * 了解.Net、C语言 * 具有良好的java面向对象编程和良好的编码规范 五、项目经验 项目一:网络教学平台系统 * 发展时长:6个月 * 发展工具:MyEclipse8.6+Dreamweave8+Sqlserver * 软件环境:...

Global site tag (gtag.js) - Google Analytics