zoukankan      html  css  js  c++  java
  • IBatis入门

    iBatis 简介:

    iBatis 是apache 的一个开源项目,一个O/R Mapping 解决方案,iBatis 最大的特点就是小巧,上手很快。如果不需要太多复杂的功能,iBatis 是能够满足你的要求又足够灵活的最简单的解决方案,现在的iBatis 已经改名为Mybatis 了。

    官网为:http://www.mybatis.org/

    二、iBatis的工作原理与流程

     iBatis使用简单的xml描述文件将JavaBean,Map实现和基本数据类型的包装类(String,Integer等)映射成JDBC的PreparedStatement的输入参数和ResultSet结果集,流程如下:

       1、在sqlMapConfig的XML配置文件中进行数据库连接的配置,XML配置文件名称任意,比如SqlMapConfig.xml

       2、在sqlMapConfig的XML配置文件中引用sqlMap的XML配置文件

      <sqlMap resource="User.xml"/>

      <sqlMap url="file://User.xml"/>

    3、在sqlMap的XML配置文件中进行SQL的配置,文件名称任意

    4、通过SqlMapClientBuilder生成具体的操作sqlMap配置文件中的SQL文的ibatis对象SqlMapClient

      String resource="SqlMapConfig.xml"

      Reader reader=Resources.getResourceAsReader(resource);

      SqlMapClient  sqlMap=SqlMapClientBuilder.buildSqlMapClient(reader);

    5、SqlMapClient对象提供函数,函数的参数对应替换sqlMap配置文件中的id,parameter等属性,完成SQL文的执行。

      public List queryForList(String statementName, Object parameterObject, int skipResults, int maxResults)

      statement:SqlMap配置中id属性,parameterObject:sqlMap配置中parameter###属性

    搭建iBatis 开发环境:

    1 、创建工程,导入相关的jar 包,ibatis.jar 、mysql.jar

    2 、编写配置文件:

    总属性文件:application-global.properties

    总配置文件:SqlMapConfig.xml

    每个实体的映射文件(Map 文件):User.xml

    application-global.properties

    driverClass=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/ibatis
    username=root
    password=123456

    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>
    
        <!-- 引用JDBC属性的配置文件 -->
        <properties resource="application-global.properties" />
    
        <!-- 默认配置 -->
        <settings cacheModelsEnabled="true" enhancementEnabled="true"
            lazyLoadingEnabled="true" errorTracingEnabled="true" maxRequests="32"
            maxSessions="10" maxTransactions="5" useStatementNamespaces="false" />
    
        <!-- 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">
            <dataSource type="SIMPLE">
                <property name="JDBC.Driver" value="${driverClass}" />
                <property name="JDBC.ConnectionURL" value="${url}" />
                <property name="JDBC.Username" value="${username}" />
                <property name="JDBC.Password" value="${password}" />
            </dataSource>
        </transactionManager>
    
        <!-- 这里可以写多个实体的映射文件 -->
        <sqlMap resource="User.xml" />
    
    </sqlMapConfig>  

    User.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="user">
    
        <typeAlias alias="User" type="org.apache.ibatis.bo.User" />
        
        <insert id="insertUser" parameterClass="User">
            insert into user values (#id#,#name#,#sex#)
        </insert>
        
        <delete id="deleteById" parameterClass="int">
             delete from user where id=#id#
        </delete>
        
        <update id="updateUser" parameterClass="User">
             update user set name=#name#,sex=#sex# where id=#id#
        </update>
        
        <select id="queryById" parameterClass="int" resultClass="User">
             select * from user where id=#id#
        </select>
        
        <select id="queryAllUsers" resultClass="User">
             select * from user
        </select>
    </sqlMap>

    User.java

    package org.apache.ibatis.bo;
    
    import java.io.Serializable;
    import java.util.List;
    
    public class User implements Serializable {
        
        /**
         * 
         */
        private static final long serialVersionUID = -5560728144383386239L;
    
        int id;
        String name;
        int sex;
        List<Role> roles;
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getSex() {
            return sex;
        }
    
        public void setSex(int sex) {
            this.sex = sex;
        }
    
        public List<Role> getRoles() {
            return roles;
        }
    
        public void setRoles(List<Role> roles) {
            this.roles = roles;
        }
    
        @Override
        public String toString() {
            return "id=" + id + ",name=" + name + ",sex=" + sex;
        }
    }

    IbatisUtils.java

    package org.apache.ibatis.util;
    
    import java.io.IOException;
    import java.io.Reader;
    import java.sql.SQLException;
    import java.util.List;
    
    import org.apache.ibatis.bo.User;
    
    import com.ibatis.common.resources.Resources;
    import com.ibatis.sqlmap.client.SqlMapClient;
    import com.ibatis.sqlmap.client.SqlMapClientBuilder;
    
    /**
     * 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 IBatisUtils {
    
        /**
         * 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("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.getMessage(), e);
            }
        }
    
        public static void createUser(String paramString) throws SQLException {
            sqlMapper.update(paramString, null);
        }
    
        public static void dropUser(String paramString) throws SQLException {
            sqlMapper.update(paramString, null);
        }
    
        public static List<?> queryAllUsers(String paramString) throws SQLException {
            return sqlMapper.queryForList(paramString);
        }
    
        public static User selectUserById(String paramString, int id)
                throws SQLException {
            return (User) sqlMapper.queryForObject(paramString, id);
        }
    
        public static void insertUser(String paramString, User user)
                throws SQLException {
            sqlMapper.insert(paramString, user);
        }
    
        public static void updateUser(String paramString, User user)
                throws SQLException {
            sqlMapper.update(paramString, user);
        }
    
        public static void deleteUser(String paramString, int id)
                throws SQLException {
            sqlMapper.delete(paramString, id);
        }
    
    }

    Main.java

    package org.apache.ibatis.test;
    
    import java.sql.SQLException;
    import java.util.Arrays;
    import java.util.List;
    
    import org.apache.ibatis.bo.User;
    import org.apache.ibatis.util.IBatisUtils;
    
    public class Main {
    
        public void insertUser() throws SQLException {
            User user = new User();
            user.setId(0);
            user.setName("张三");
            user.setSex(1);
            IBatisUtils.insertUser("insertUser", user);
            System.out.println("insert success!, user = " + user);
        }
    
        private void queryAllUsers() throws SQLException {
            List<?> list = IBatisUtils.queryAllUsers("queryAllUsers");
            for (int i = 0; i < list.size(); i++) {
                User user = (User) list.get(i);
                System.out.println(user);
            }
            System.out.println(Arrays.toString(list.toArray()));
        }
    
        public static void main(String[] args) {
            Main main = new Main();
            try {
                main.queryAllUsers();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    
    }

    至此,测试结束

    FAQ:

    1、com.ibatis.sqlmap.client.SqlMapException: There is already a statement named xxx in this SqlMap.

    Exception in thread "main" java.lang.ExceptionInInitializerError
        at org.apache.ibatis.data.Main.selectAllAccounts(Main.java:23)
        at org.apache.ibatis.data.Main.main(Main.java:59)
    Caused by: java.lang.RuntimeException: Error occurred.  
    Cause: com.ibatis.common.xml.NodeletException: Error parsing XML. Cause: java.lang.RuntimeException: Error parsing XPath
    '/sqlMapConfig/sqlMap'. Cause: com.ibatis.common.xml.NodeletException: Error parsing XML. Cause: java.lang.RuntimeException: Error parsing XPath '/sqlMap/select'.
    Cause: com.ibatis.sqlmap.client.SqlMapException: There is already a statement named selectById in this SqlMap. at com.ibatis.sqlmap.engine.builder.xml.SqlMapConfigParser.parse(SqlMapConfigParser.java:89) at com.ibatis.sqlmap.client.SqlMapClientBuilder.buildSqlMapClient(SqlMapClientBuilder.java:63) at org.apache.ibatis.data.IBatisUtils.<clinit>(IBatisUtils.java:35) ... 2 more

    这个是因为存在相同的SQL ID

    解决方案如下:

    <!-- 启用命名空间 -->
    <settings useStatementNamespaces="true" />

    useStatementNamespaces
    如果启用本属性,必须使用全限定名来引用 mapped useStatementNamespaces statement

    Mapped statement 的全限定名由 sql-map 的名称和 mapped-statement 的名称合成。例如: queryForObject("sqlMapName.statementName");
    缺省值:false(禁用)

    2、org.xml.sax.SAXParseException: The content ofelement type “sqlMapConfig” must match“(properties?,settings?,resultObjectFactory?,ypeAlias*,typeHandler*,transactionManager?,sqlMap+)+”

    Exception in thread "main" java.lang.ExceptionInInitializerError
        at org.apache.ibatis.data.Main.selectAllAccounts(Main.java:23)
        at org.apache.ibatis.data.Main.main(Main.java:59)
    Caused by: java.lang.RuntimeException: Error occurred.  Cause: com.ibatis.common.xml.NodeletException: Error parsing XML.  Cause: org.xml.sax.SAXParseException: The content of element type "sqlMapConfig" must match "(properties?,settings?,resultObjectFactory?,typeAlias*,typeHandler*,transactionManager?,sqlMap+)+".
        at com.ibatis.sqlmap.engine.builder.xml.SqlMapConfigParser.parse(SqlMapConfigParser.java:89)
        at com.ibatis.sqlmap.client.SqlMapClientBuilder.buildSqlMapClient(SqlMapClientBuilder.java:63)
        at org.apache.ibatis.data.IBatisUtils.<clinit>(IBatisUtils.java:35)
        ... 2 more
    Caused by: com.ibatis.common.xml.NodeletException: Error parsing XML.  Cause: org.xml.sax.SAXParseException: The content of element type "sqlMapConfig" must match "(properties?,settings?,resultObjectFactory?,typeAlias*,typeHandler*,transactionManager?,sqlMap+)+".
        at com.ibatis.common.xml.NodeletParser.parse(NodeletParser.java:53)
        at com.ibatis.sqlmap.engine.builder.xml.SqlMapConfigParser.parse(SqlMapConfigParser.java:86)
        ... 4 more
    Caused by: org.xml.sax.SAXParseException: The content of element type "sqlMapConfig" must match "(properties?,settings?,resultObjectFactory?,typeAlias*,typeHandler*,transactionManager?,sqlMap+)+".
        at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:195)
        at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:131)
        at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:384)
        at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:318)
        at com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator.handleEndElement(XMLDTDValidator.java:2017)
        at com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator.endElement(XMLDTDValidator.java:901)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1782)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2939)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:647)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:511)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:808)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
        at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119)
        at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:232)
        at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:284)
        at com.ibatis.common.xml.NodeletParser.createDocument(NodeletParser.java:157)
        at com.ibatis.common.xml.NodeletParser.parse(NodeletParser.java:50)
        ... 5 more

    这个是因为ibatis配置文件sqlMapConfig的属性是有顺序的,配置顺序properties,settings,resultObjectFactory,typeAlias*,typeHandler*,transactionManager,sqlMap 。

    附录:

    1、SqlMapConfig.xml中的setting属性

    <settings
    cacheModelsEnabled="true"
    lazyLoadingEnabled="false"
    enhancementEnabled="true"
    maxSessions="64"
    maxTransactions="8"
    maxRequests="128"
    useStatementNamespaces="false"
    classInfoCacheEnabled="true"
    errorTracingEnabled="true"
    defaultStatementTimeout=""
    statementCachingEnabled="true"
    />
    <!--
    maxRequests
    同时执行 SQL 语句的最大线程数。大于这个值的线程将阻塞直到另一个线程执行完成。不同的 DBMS有不同的限制值,但任何数据库都有这些限制。通常这个值应该至少是maxTransactions(参见以下)的 10 倍,并且总是大于 maxSessions 和maxTranactions。减小这个参数值通常能提高性能。

    例如:maxRequests=“256”
    缺省值:512

    maxSessions
    同一时间内活动的最大 session 数。一个 session 可以maxSessions是代码请求的显式 session,也可以是当线程使用SqlMapClient 实例(即执行一条语句)自动获得的session。它应该总是大于或等于 maxTransactions 并小于 maxRequests。减小这个参数值通常能减少内存使用。

    例如:maxSessions=“64”
    缺省值:128

    maxTransactions
    同时进入 SqlMapClient.startTransaction()的最大线程maxTransactions 数。大于这个值的线程将阻塞直到另一个线程退出。不同的 DBMS 有不同的限制值,但任何数据库都有这些限制。这个参数值应该总是小于或等于maxSessions 并总是远远小于 maxRequests。减小这个参数值通常能提高性能。

    例如:maxTransactions=“16”
    缺省值:32

    cacheModelsEnabled
    全局性地启用或禁用 SqlMapClient 的所有缓存cacheModelsEnabled model。调试程序时使用。

    例如:cacheModelsEnabled=“true”
    缺省值:true(启用)

    lazyLoadingEnabled
    全局性地启用或禁用SqlMapClient的所有延迟加载。lazyLoadingEnabled 调试程序时使用。
    例子:lazyLoadingEnabled=“true”
    缺省值:true(启用)

    enhancementEnabled
    全局性地启用或禁用运行时字节码增强,以优化访enhancementEnabled
    问Java Bean属性的性能,同时优化延迟加载的性能。

    例子:enhancementEnabled=“true”
    缺省值:false(禁用)

    useStatementNamespaces
    如果启用本属性,必须使用全限定名来引用 mapped useStatementNamespaces
    statement。Mapped statement 的全限定名由 sql-map 的名称和 mapped-statement 的名称合成。例如: queryForObject("sqlMapName.statementName");

    例如:useStatementNamespaces=“false”
    缺省值:false(禁用)

    defaultStatementTimeout
    此设置值必须为一个整数,作为JDBC连接超时的时间,这个值可以被任意一个映射文件的statement属性来重新设置,
    如果没有指明,查询将无超时时间限制除非在映射文件中设置statement属性值。被设置的值以秒为单位等待连接失效

    classInfoCacheEnabled 
    With this setting enabled, iBATIS will maintain a cache of introspected
    classes. This will lead to a significant reduction in startup time if many
    classes are reused.
    例如: classInfoCacheEnabled=“true”
    缺省值: true (启用)

    statementCachingEnabled (iBATIS 2.3.0以后版本中有)
    With this setting enabled, iBATIS will maintain a local cache of
    prepared statements. This can lead to significant performance
    improvements.
    例如: statementCachingEnabled=“true”
    缺省值: true (启用)

  • 相关阅读:
    面向对象编程
    多任务-线程
    浅析IoC框架
    Android:关于声明文件中android:process属性说明
    Android闹钟设置的解决方案
    【转】RelativeLayout和LinearLayout及FrameLayout性能分析
    SurfaceView浅析
    SQLite Vacuum
    SQLiteStatement优化SQLite操作
    基于Android SQLite的升级详解
  • 原文地址:https://www.cnblogs.com/kofxxf/p/3878720.html
Copyright © 2011-2022 走看看