• mybatis框架的搭建与mybatis-config.xml的配置


    mybatis框架简介

    mybatis框架与Hibernate框架相比来说,专注于SQL语句,对SQL语句的编写能力要求较高,同时对数据库的事务也需要有好的理解,最主要的功能是mybatis框架可以将查询到的结果集自动封装成对象。

    首先要进行一个环境的搭建:

      在这里我使用的IDE是eclipse

      使用的mybatis的版本是3.4.6的,同时也将源码的jar包下载下来,还有必备的两个DTD约束文件mybatis-3-mapper.dtd和mybatis-3-config.dtd

      使用的数据库是MySQL

      由于mybatis也是相当于对JDBC的封装,所以需要JDBC的jar包

      我也加入了一个log4j的日志支持

      

    我们需要先将项目搭建起来

      

    数据库建表:

    create table tbl_customer(
    id int primary key auto_increment,
    name varchar(20) ,
    password varchar(200),
    zip varchar(20),
    address varchar(200),
    telephone varchar(15),
    email varchar(50)
    );
    create table tbl_book( id int primary key auto_increment, name varchar(100), price double ); create table tbl_order( id int primary key auto_increment, cost double, orderDate date, customer_id int references tbl_customer(id) ); create table tbl_orderline( id int primary key auto_increment, num int, order_id int references tbl_order(id), book_id int references tbl_book(id) );
    insert into tbl_book values(1,'JAVA核心技术',81); insert into tbl_book values(2,'UNIX技术手册',21); insert into tbl_book values(3,'ORACLE9I参考手册',108); insert into tbl_book values(4,'JSP设计(第三版)',59); insert into tbl_book values(5,'JAVA SERVLET 编程(第二版)',38); insert into tbl_book values(6,'XML 高级编程(第2版)',97); insert into tbl_book values(7,'精通STRUTS:基于MVC的JAVA WEB设计与开发',36); insert into tbl_book values(8,'精通HIBERNATE:JAVA对象持久化技术详解',44); insert into tbl_book values(9,'SPRING IN ACTION中文版',29); insert into tbl_book values(10,'精通EJB 3.0',44);

    逆向数据库到模型:

    我觉得,对于mybatis框架来说,最要紧的就是两个配置文件,mybatis-config.xml和XxxxMapper.xml文件了,所以就从mybatis-config.xml开始说起吧。

    首先呢是mybatis-config.xml文件的头部:

    <?xml version="1.0" encoding="utf-8"?> 
    <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 
    "http://mybatis.org/dtd/mybatis-3-config.dtd"> 

    可以看出这个xml文件引用了一个DTD文件的约束,所以说对框架来说是个有效的xml文件,这个两个文件都可以在官网上下载,mybatis框架也是个开源的框架,这一点是很好的

    注意:!!!这个xml文件由于dtd的约束使得标签的顺序唯一,标签如果出现就必须按照严格的顺序书写(IDE是可以联网关联的,也可以自己设置)

    我们来看这个xml文件的一个大致结构

    <?xml version="1.0" encoding="utf-8"?> 
    <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 
    "http://mybatis.org/dtd/mybatis-3-config.dtd"> 
    
    <configuration>
    </configuration> 

    configuration这个标签中就是需要给框架配置的一系列标签。

    首先是properties标签:

    属性配置元素properties可以将配置值写死到mybatis-config.xml中,也可以具体到一个属性文件中,并且使用属性文件的key名作为占位符,在下述的配置中,我们将数据库连接属性配置到了application.properties文件中,并且为driver,URL等属性使用了占位符。

    在applications.properties文件中配置数据库连接参数,如下所示:
    jdbc.driverClassName=oracle.jdbc.driver.OracleDriver
    jdbc.url=jdbc:oracle:thin:@127.0.0.1:1521:XE
    jdbc.username=xxx 
    jdbc.password=xxx

    <properties resource="application.properties"> 
        <!-- 这是设置优先级比较低的默认属性 -->
        <property name="username" value="db_user" /> 
        <property name="password" value="verysecurepwd" /> 
    </properties> 

    这样我们就可以在environment标签中调用上述配置文件中的K-V值了:

    envionment标签是环境相关设置标签,使用如下:

    <!-- 这里的环境可以有多个,环境id不同,作用不同,如下,第一个environment作用是开发,第一个environment作用是生产 -->
      <environments default="development"> 
         <!-- 这里的id是指环境的id,常常写为自己的作用 -->
        <environment id="development"> 
        <!-- 这个属性是连接管理类型 一般有2个值可选-->
          <!-- JDBC 是需要应用程序自己管理事务  -->
          <!-- 例如,部署到ApacheTomcat的应用程序,需要应用程序自己管理事务。因为ApacheTomcat不会帮我们管理事务。 -->
          <!-- MANAGED 是让服务器自动管理事务 像glassfish 服务器-->
          <transactionManager type="JDBC" /> 
          <!-- dataSource的类型type属性可以配置成其内置类型之一,如UNPOOLED,POOLED,JNDI。 -->
          <dataSource type="POOLED"> 
    <property name="driver" value="${jdbc.driverClassName}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </dataSource> </environment> <environment id="production"> <transactionManager type="MANAGED" /> <dataSource type="JNDI"> <property name="data_source" value="java:comp/jdbc/MyBatisDemoDS" /> </dataSource> </environment> </environments>

    typeAliases标签:这个标签是起个别名的作用

    <!-- 这个属性就是对pojo类起个别名 -->
    <typeAliases> 
        <!-- 这里的意思是将 pojo.Student 类别名为 Student-->
        <typeAlias alias="Student" type="pojo.Student" /> 
        <!-- 这里的意思是将 pojo包下的所有类进行别名,比如pojo.Student 就会别名为student-->
        <!-- 优先级不高-->
        <package name="pojo" /> 
    </typeAliases> 

    接下来是一个比较复杂的问题:

    类型处理器,这是一个在mybatis中相对复杂的问题,分为两种情况,一是内建的类型处理器,再者是自己定义的类型

    MyBatis对于以下的类型使用内建的类型处理器
    所有的基本数据类型、基本类型的包裹类型
    byte[]、java.util.Date、java.sql.Date、java,sql.Time、java.sql.Timestamp、java枚举类型等

    如果是自己定义的类型,例子如下
    假如在XxxxMapper.xml文件中配置一个insert插入语句,这里的phone是Student的一个内置对象,类型为PhoneNumber:

    <insert id="insertStudent" parameter Type="Student">
        insert into students(name,email,phone)
        values(#{name},#{email},#{phone})
    </insert> 

    为了让MyBatis明白怎样处理这个自定义的Java对象类型,如PhoneNumber,我们可以创建一个自定义的类型处理器,首先我们需要处理PhoneNumber类,加入一个getAsString方法

    public class PhoneNumber{ 
        
        private String countryCode; 
        private String stateCode; 
        private String number; 
        
        public PhoneNumber(){}
    
        public PhoneNumber(String countryCode, String stateCode, String number){ 
            this.countryCode = countryCode; 
            this.stateCode = stateCode; 
            this.number = number; 
        }
    
        public PhoneNumber(String str){ 
            if(str!=null){
                String[] args = str.split("-");
                this.countryCode = args[0];
                this.stateCode = args[1];
                this.number = args[2];
            }
        }
    
        public String getAsString() { 
            return countryCode + "-" + stateCode + "-" + number; 
        } 
        // Setters and getters 
    }            

    MyBatis提供了抽象类BaseTypeHandler<T> ,我们可以继承此类创建自定义类型处理器。

    public class PhoneTypeHandler extends BaseTypeHandler<PhoneNumber>{
    
            //遇到PhoneNumber参数的时候应该如何在ps中设置值
            @Override
            public void setNonNullParameter(PreparedStatement ps, int i, PhoneNumber parameter, JdbcType jdbcType)
                    throws SQLException {
                //这个方法就是调用了PhoneNumber类中的getAsString方法
                //将这个对象以一个字符串的方式存入对应的表字段中
                ps.setString(i, parameter.getAsString());
            }
    
            //查询中遇到PhoneNumber类型的应该如何封装(使用列名封装)
            @Override
            public PhoneNumber getNullableResult(ResultSet rs, String columnName) throws SQLException {
                //由上面的方法可以知道
                //这个方法可以将以字符串的方式存入对应的表字段中的PhoneNumber对象取出来
                //调用了PhoneNumber类中的一参构造器重新封装为对象
                return new PhoneNumber(rs.getString(columnName));
            }
    
            //查询中遇到PhoneNumber类型的应该如何封装(使用列的下标)
            @Override
            public PhoneNumber getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
                return new PhoneNumber(rs.getString(columnIndex));
            }
    
            //CallableStatement使用中遇到了PhoneNumber类型的应该如何封装
            @Override
            public PhoneNumber getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
                return new PhoneNumber(cs.getString(columnIndex));
            }
    }

     

    最后就需要在mybatis-config.xml文件中配置一下

      <typeHandlers> 
        <typeHandler handler="typehandlers.PhoneTypeHandler" /> 
        <!--这个标签貌似也是个别名的作用,不过我没用过-->
        <package name="typehandlers" /> 
      </typeHandlers> 

    接下来是mappers元素,主要用于 SQL映射

    SQLMapper文件中主要是对SQL语句的映射,表明这个sql语句对应哪个方法的调用。我们需要在mybatis-config.xml文件中配置 SQLMapper文件的位置。

    resource属性用来指定在classpath中的mapper文件。
    url属性用来通过完全文件系统路径或者web URL地址来指向mapper文件
    class属性用来指向一个mapper接口
    package属性用来指向可以找到Mapper接口的包名 

    其实在项目中常常只要一个属性就足够定位了

      <mappers> 
        <mapper resource="mappers/StudentMapper.xml" /> 
        <mapper url="file:///D:/mybatisdemo/app/mappers/StudentMapper.xml" /> 
        <mapper class="mappers.StudentMapper" /> 
        <package name="com.mappers" /> 
      </mappers> 

    最后是settings元素: 全局参数设置

    settings元素有好多的参数设置

    注意:大多数情况下,【这些参数使用它们的默认值即可】

    <settings>
              <!-- 这个配置使全局的映射文件启用或禁用缓存 -->
              <setting name="cacheEnabled" value="true" />
              <!-- 全局启用或禁用延迟加载。当禁用时,所有关联对象都会即时加载 -->
              <setting name="lazyLoadingEnabled" value="true" />
              <!-- 允许或不允许多种结果集从一个单独的语句中返回(需要适合的驱动) -->
              <setting name="multipleResultSetsEnabled" value="true" /> 
              <!-- 使用列标签代替列名。不同的驱动在这方便表现不同。参考驱动文档或充分测试两种方法来决定所使用的驱动 -->
              <setting name="useColumnLabel" value="true" /> 
              <!-- 允许JDBC支持生成的键。需要适合的驱动。 -->
              <setting name="useGeneratedKeys" value="false" /> 
              <!-- 指定MyBatis如何自动映射列到字段/属性。PARTIAL只会自动映射简单、没有嵌套的结果。FULL会自动映射任意复杂的结果(嵌套的或其他情况) -->
              <setting name="autoMappingBehavior" value="PARTIAL" />
              <!-- 配置默认的执行器。SIMPLE执行器没有什么特别之处。REUSE执行器重用预处理语句。BATCH执行器重用语句和批量更新 -->
              <setting name="defaultExecutorType" value="SIMPLE" /> 
              <!-- 设置超时时间,它决定驱动等待一个数据库响应的时间 -->
              <setting name="defaultStatementTimeout" value="25000" />         
              <!-- 允许在嵌套语句中使用分页(RowBounds)默认false -->
              <setting name="safeRowBoundsEnabled" value="false" /> 
              <!-- 是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。默认false -->
              <setting name="mapUnderscoreToCamelCase" value="false" /> 
              <!-- MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。 默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。 若设置值为 STATEMENT,本地会话仅用在语句执行上,对相同 SqlSession 的不同调用将不会共享数据。 -->
              <setting name="localCacheScope" value="SESSION" /> 
              <!-- 当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。 某些驱动需要指定列的 JDBC 类型,多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。 -->
              <setting name="jdbcTypeForNull" value="NULL" />
              <!-- 指定对象的哪个方法触发一次延迟加载。 -->
              <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode ,toString" /> 
              <!-- CGLIB | JAVASSIST 默认JAVASSIST(MyBatis 3.3 or above)  -->
              <!-- 指定 Mybatis 创建具有延迟加载能力的对象所用到的代理工具。 -->
              <setting name="proxyFactory" value="JAVASSIST" /> 
              <!-- 当启用时,对任意延迟属性的调用会使带有延迟加载属性的对象完整加载;反之,每种属性将会按需加载。 -->
              <setting name="aggressiveLazyLoading" value="true" />           
              <!-- 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 -->
              <setting name="logImpl" value="LOG4J " /> 
              <!-- 指定 MyBatis 增加到日志名称的前缀。值可以是任意字符串 -->
              <setting name="logPrefix" value="LOG4J " /> 
              <!-- 指定当结果集中值为 null 的时候是否调用映射对象的 setter(map 对象时为 put)方法,这对于有 Map.keySet() 依赖或 null 值初始化的时候是有用的。注意基本类型(int、boolean等)是不能设置成 null 的。 默认false-->
              <setting name="callSettersOnNulls" value="false " /> 
    </settings> 

    拿其中的一个我认为最常用的,比如 <setting name="jdbcTypeForNull" value="NULL" /> 这个设置就可以有效的帮助我们避免“1111”错误

    这个配置是说如果当插入的值为空时给一个NULL属性,就避免了“1111”错误,比如我在将一个对象插入到表中的时候,一个属性没有值,在有些环境中数据库无法解析这个空的指向,就会报出“1111”错误,如果设置了这个属性这个空的指向就可以设为空

    在package org.apache.ibatis.type包中中有一个枚举JdbcType,定义了一系列类型,但是一个数据库不可能完全支持这些类型,源码如下:

    package org.apache.ibatis.type;
    
    import java.sql.Types;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
    * @author Clinton Begin
    */
    public enum JdbcType {
    /*
    * This is added to enable basic support for the
    * ARRAY data type - but a custom type handler is still required
    */
    ARRAY(Types.ARRAY),
    BIT(Types.BIT),
    TINYINT(Types.TINYINT),
    SMALLINT(Types.SMALLINT),
    INTEGER(Types.INTEGER),
    BIGINT(Types.BIGINT),
    FLOAT(Types.FLOAT),
    REAL(Types.REAL),
    DOUBLE(Types.DOUBLE),
    NUMERIC(Types.NUMERIC),
    DECIMAL(Types.DECIMAL),
    CHAR(Types.CHAR),
    VARCHAR(Types.VARCHAR),
    LONGVARCHAR(Types.LONGVARCHAR),
    DATE(Types.DATE),
    TIME(Types.TIME),
    TIMESTAMP(Types.TIMESTAMP),
    BINARY(Types.BINARY),
    VARBINARY(Types.VARBINARY),
    LONGVARBINARY(Types.LONGVARBINARY),
    NULL(Types.NULL),
    OTHER(Types.OTHER),
    BLOB(Types.BLOB),
    CLOB(Types.CLOB),
    BOOLEAN(Types.BOOLEAN),
    CURSOR(-10), // Oracle
    UNDEFINED(Integer.MIN_VALUE + 1000),
    NVARCHAR(Types.NVARCHAR), // JDK6
    NCHAR(Types.NCHAR), // JDK6
    NCLOB(Types.NCLOB), // JDK6
    STRUCT(Types.STRUCT),
    JAVA_OBJECT(Types.JAVA_OBJECT),
    DISTINCT(Types.DISTINCT),
    REF(Types.REF),
    DATALINK(Types.DATALINK),
    ROWID(Types.ROWID), // JDK6
    LONGNVARCHAR(Types.LONGNVARCHAR), // JDK6
    SQLXML(Types.SQLXML), // JDK6
    DATETIMEOFFSET(-155); // SQL Server 2008
    
    public final int TYPE_CODE;
    private static Map<Integer,JdbcType> codeLookup = new HashMap<Integer,JdbcType>();
    
    static {
    for (JdbcType type : JdbcType.values()) {
    codeLookup.put(type.TYPE_CODE, type);
    }
    }
    
    JdbcType(int code) {
    this.TYPE_CODE = code;
    }
    
    public static JdbcType forCode(int code) {
    return codeLookup.get(code);
    }
    
    }

    常用的标签就这些了,这些标签的顺序为

    properties,settings,typeAliases,typeHandlers,environments,mappers

     

  • 相关阅读:
    celery beat之pidfile already exists问题
    HBase源码系列之HFile
    吴裕雄--天生自然 JAVA开发学习:集合框架
    吴裕雄--天生自然 诗经:小池
    吴裕雄--天生自然 诗经:所见
    吴裕雄--天生自然 JAVA开发学习:数据结构
    吴裕雄--天生自然 JAVA开发学习:包(package)
    吴裕雄--天生自然 JAVA开发学习:接口
    吴裕雄--天生自然 JAVA开发学习:封装
    吴裕雄--天生自然 JAVA开发学习:抽象类
  • 原文地址:https://www.cnblogs.com/Magic-Li/p/11680156.html
Copyright © 2020-2023  润新知