Mybatis学习笔记之三:Mybatis的常用配置介绍

现在许多框架都提供了两种配置方式,文件配置和注解配置

文件配置主要使用xml文件,其他的还有properties,yml等。注解则是嵌入代码中。看到这儿应该明白,注解配置是与代码嵌在一起,没有解耦。而配置文件则是与代码分离开来,但是在实际开发中,很少有这种情况:修改配置文件但不修改代码的。

Mybatis也提供了注解和文件两种配置。这儿着重介绍文件配置的方式,因为Mybatis主要就是使用文件配置,如果使用注解,那么Myabtis的sql语句与代码分离这个优势就不存在了。

Mybatis的配置文件主要分为两部分,mybatis全局配置文件和mapper配置文件。

1、Mybatis的全局配置文件: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">
<configuration>
</configuration>

所有的配置都必须在configuration标签之间。

1.1、Properties配置。

 前面用到了properties这个标签,在resources属性中引入了db.properties。这个标签顾名思义就是配置属性的。

<properties resource="jdbc.properties">
	<property name="username" value="zhangsan"/>
	<property name="password" value="123"/>
</properties>
可以使用resource属性引入配置文件,也可以使用url属性引入,但注意resource和url两个属性不能同时指定,虽然你可以在配置文件中这样书写(不会报错),但是当初始化时就会抛出异常。初始化代码为org.apache.ibatis.builder.xml.XMLConfigBuilder的propertiesElement(XNode)方法,代码如下:

if (context != null) {
      Properties defaults = context.getChildrenAsProperties();
      String resource = context.getStringAttribute("resource");
      String url = context.getStringAttribute("url");
     //同时指定了resource和url会报错
      if (resource != null && url != null) {
        throw new BuilderException("The properties element cannot specify both a URL and a resource based property file reference.  Please specify one or the other.");
      }
      if (resource != null) {
        defaults.putAll(Resources.getResourceAsProperties(resource));
      } else if (url != null) {
        defaults.putAll(Resources.getUrlAsProperties(url));
      }
      Properties vars = configuration.getVariables();
      if (vars != null) {
        defaults.putAll(vars);
      }
      parser.setVariables(defaults);
      configuration.setVariables(defaults);
    }
也可以使用property指定单个属性,但注意代码中的property会覆盖resource或者url引入的配置,也会覆盖property标签配置的属性,这是因为解析顺序为:property标签-->引入的配置文件 --> 代码中的properties。且是使用Properties这个类来存储的,关于Properties类,可以自己使用一下。可以使用${}引用前面配置的属性。

值得注意的是:如果要使用properties这个标签,那么必须将该标签放在其他标签之前,且一个配置文件中只能出现一次properties标签。

1.2 settings全局的设置

<settings>
  <!--是否开启全局缓存  -->
  <setting name="cacheEnabled" value="true"/>
  <!--是否开启延迟加载  -->
  <setting name="lazyLoadingEnabled" value="true"/>
  <!--自动映射到字段或者属性 NONE表示取消映射,PARTIAL只会映射没有定义嵌套结果集的映射,FULL自动映射
                    不管是否嵌套,默认是PARTIAL  -->
  <setting name="autoMappingBehavior" value="PARTIAL"/>
  <!--指定发生自动映射目标未知列的反应,NONE表示不做任何反应,WARNING输出日志提醒,FALLING映射失败
                    默认为NONE-->
  <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
  <!--配置执行器,SIMPLE普通执行器,默认为SIMPLE,还有RESUME、BATCH  -->
  <setting name="defaultExecutorType" value="SIMPLE"/>
  <!--设置超时时间  -->
  <setting name="defaultStatementTimeout" value="25"/>
  <!--是否开启自动驼峰命名规则,比如member_id映射为memberId,默认为false,建议开启  -->
  <setting name="mapUnderscoreToCamelCase" value="false"/>
  <!--本地缓存的范围,是SESSION还是STATEMENT  -->
  <setting name="localCacheScope" value="SESSION"/>
  <!--指定使用何种日志,Mybatis支持SLF4J、Apache Commons Logging、Log4j 2、
      Log4j、JDK logging,它会从列出的顺序查找,如果一个都没找到,日志就会被禁用,可以在这儿指定 -->
  <setting name="logImpl" value="LOG4J"/>
</settings>
注意:settings里面至少包含一个setting

1.3 typeAliases别名配置,这个标签存在的意义仅是为了减少冗余。

      正如上篇看到的,如果不配置这个属性,那么配置文件中就必须使用类的全称限定名。例如配置这个属性前使用org.yamikaze.model.User,配置后使用User,大大减少了冗余。也可以使用typeAlias配置单个别名。如下所示:

<typeAliases>
	<!--为单个类型配置别名  -->
    <typeAlias type="org.yamikaze.model.User" alias="user"/>
	<!--如果不指定别名,别名为类型的简称Student  -->
	<typeAlias type="org.yamikaze.model.Student"/>
	<package name="org.yamikaze.model"/>
</typeAliases>
注意:这个标签配置最多出现一次,且typeAlias必须在package前面,而且不能有相同的别名,否则报错。
1.4、配置开发环境environments。

<environments default="development1">
		<!--可以配置多个开发环境,但是外层的默认开发环境必须是配置的其中一个环境  -->
		<environment id="development1">
			<!--配置事务管理,这儿使用JDBC的事务  -->
			<transactionManager type="JDBC"/>
			<dataSource type="POOLED">
			<!--配置与数据库的连接  -->
			<!--使用${}获取前面引入的配置文件  -->
				<property name="driver" value="${driver}"/>
				<property name="url" value="${url}"/>
				<property name="username" value="${user}"/>
				<property name="password" value="${password}"/>
			</dataSource>
		</environment>
		
		<environment id="development2">
			<!--配置事务管理,这儿使用JDBC的事务  -->
			<transactionManager type="JDBC"/>
			<dataSource type="POOLED">
			<!--配置与数据库的连接  -->
			<!--使用${}获取前面引入的配置文件  -->
				<property name="driver" value="${driver}"/>
				<property name="url" value="${url}"/>
				<property name="username" value="${user}"/>
				<property name="password" value="${password}"/>
			</dataSource>
		</environment>
	</environments>
可以配置多个环境,但是只能使用其中一个。环境一定要配置环境的id,事务管理器以及数据源。同时一定要指定默认的环境。事务管理器一般使用JDBC来提交回滚,数据源Mybatis内置了三种,POOLED、UNPOOLED、JNDI。当然你可以使用第三方数据源,比如DBCP、C3P0、Druid等。

1.5、映射器mappers。

        用于指定实体类对应的配置文件或者接口。

<mappers>
	<!--可以通过包名指定,但是指定的是接口  -->
	<package name="org.yamikaze.model"/>
	<!--通过resource指定,指定的是文件  -->
	<mapper resource="cn/yamikaze/model/User.xml"/>
	<!--通过class单个类指定,指定的是接口  -->
	<mapper class="org.yamikaze.dao.IUserDao"/>
	<!--通过url指定,指定的是文件  -->
	<mapper url="file:///var/org/yamikaze/model/user.xml"/>
</mappers>

注意:如果你使用的是注解配置,那么指定接口,否则指定配置文件。一般使用resource指定配置文件。

configuration下面还有许多标签配置,单个人感觉不是很常用。更多配置参考http://www.mybatis.org/mybatis-3/zh/index.html。

2、实体类mapper文件配置。

      这个配置文件配置了实体类相关的所有sql语句以及返回结果集。

     所有的配置都应该放在mapper标签之间,如:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.yamikaze.model.User">
    <insert id="save" parameterType="User" useGeneratedKeys="true" keyProperty="id">
        insert into t_user(username,password,sex) values(#{username},#{password},#{sex})
    </insert>
    <select id="loadByUsername" parameterType="string" resultType="User">
        SELECT * FROM  t_user WHERE username = #{username}
    </select>
</mapper>

2.1、insert标签、update标签、delete标签
         这几个标签用于向数据库插入数据、更新数据、删除数据。为什么要把他们放在一起?这是因为在配置文件中它们的配置几乎是一致的,差别在于sql语句的不同。如果你感兴趣的话,可以查看Mybatis的源代码,你会发现虽然可以调用session.insert()、session.delete(),但是最后实际调用的都是session的update方法。

        每个标签都共有的属性:

         id:每一个标签必须制定id,同一个配置文件不能指定相同的id,但不同的配置文件可以相同,例如,我们可以统一约定 插入语句id为save或者insert,更新语句id为update,删除语句id为delete。

         parameterType:参数类型,Mybatis内置了许多java类型,例如string、integer(int)、map等,你也可以使用你自己定义的实体类(注意配置别名)。实际上,你可以不在配置文件中配置这个属性,因为Myabtis可以通过TypeHandler判断具体传入的类型。但最好还是指定,这样比较好维护sql语句。还有一个parameterMap也可以指定参数类型,但这个属性在3版本已经被声明过时了。

         useGeneratedKeys和keyProperty,useGenerateKeys表示是否使用数据库自动生成的主键,默认是为false的,如果设置为true,同时指定了keyProperty,那么会将自动生成后的主键注入到指定的属性中,如下:

public static void main(String[] args) {
        IUserDao userDao = new UserDao();
        User u = new User();//u的Id为0,因为没有指定
        u.setUsername("tom");
        u.setSex("man");
        u.setPassword("951001");
        userDao.save(u); //save语句设置了useGeneratedKeys为true,keyProperty="id"
        System.out.print(u.getId()); //u的id为9,这是第9条数据
    }
      但是注意:这两个属性仅对insert和update语句有效。

     timeout属性:指定超时时间,会覆盖前面全局配置。

    statementType:指定使用statement还是preparedstatement还是callablestatement,默认为preparedstatement。

    一般可以这样配置:

    <insert id="save" parameterType="User" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO t_user(username,password,sex) VALUES(#{username},#{password},#{sex})
    </insert>

    <delete id="delete" parameterType="int">
        DELETE  FROM t_user WHERE id = #{id}
    </delete>
    <!--可以不用指定parameterType属性,但最好指定,便于SQL的维护-->
    <update id="update" parameterType="User">
        UPDATE t_user SET username = #{username},password = #{password},sex = #{sex}
        WHERE id = #{id}
    </update>
   注意:这三条语句可以有返回值,但是返回的是数据库数据的修改行数。

2.2、select标签。

          这个标签用于查找数据,使用频率最高的select语句。它的通用配置与insert是一致的,但不同于insert的是它有返回值。同时select语句的查询以及结果映射也是Mybatis研究的焦点。

          resultType:返回类型,如果是返回集合,那么应该是集合包含的具体类型,例如:返回List<User>,那么应该填User,而不应该是List

          resultMap:如果需要返回更复杂的类型,那么请使用resultMap。resultMap需要在配置文件中手动配置。

     <select id="loadByUsername" resultType="User" parameterType="string">
         SELECT * FROM  t_user WHERE username = #{username}
     </select>
2.3、sql标签。

         这个标签用于定义一些可重用的sql片段。比如,查找用户点赞或者收藏的文章列表时,查找出的数据类型是一样的,但是关联的表不一样,那么可以将查询的一部分提取出来重用。 例如:

    <sql id="selectColumn">
        <!--引用值是${},与insert和其他语句中的引用是不同的-->
        SELECT ${tableName1}.*,${tableName2}.*
    </sql>

    <select id="selectUser" parameterType="User">
        <!--使用include标签引用sql片段-->
        <include refid="selectColumn">
            <!--使用property标签传值-->
            <property name="tableName1" value="t_user"/>
            <property name="tableName2" value="t_card"/>
        </include>
        FROM t_user LEFT JOIN t_card ON t_user.id = t_card.uid
        WHERE t_card.id = #{id}
    </select>
2.4、resultMap标签。

         前面select标签的resultMap属性值必须是resultMap定义的。

         我们先来看下resultMap的简单结果映射。

    <select id="loadByUsername" resultType="User" parameterType="string">
        SELECT id,username,password,sex FROM  t_user WHERE username = #{username}
    </select>
       看着这条sql语句没有使用resultMap,但其实Mybatis会在幕后自动创建一个resultMap来映射。例如:数据库行名为username,对应的属性名为username那么就会精确到username属性中。也许你数据库的是user_name,那么你可以这样使用:
    <select id="loadByUsername" resultType="User" parameterType="string">
        SELECT id,user_name as username,password,sex FROM  t_user WHERE username = #{username}
    </select>
       或者配置resultMap:
    <resultMap id="userResult" type="User" autoMapping="true">
        <result property="username" column="user_name"/>
    </resultMap>
       然后在select标签的返回值使用userResult就ok了,你注意到了autoMapping=true吗?设置为true会自动映射没有用result子标签指定的属性
       然而这是单张表的映射,如果有许多关联对象的呢?比如用户与IDCARD一一关联,而用户又与商品列表一对多关联。通过查询出一个用户以及用户相对应的IDCARD和消息列表来看看这个resultMap怎么配置吧。

       IDCard实体类:  

package org.yamikaze.model;

import java.util.Date;

/**
 * Created by yamikaze on 2017/7/12.
 */
public class IDCard {
    private Long no;         //卡的编号
    private Long uid;        //关联用户的id
    private Date createTime; //绑定卡的时间
    private String type;     //卡的类型

    //setter & getter方法略
}
      Message.java
package org.yamikaze.model;

import java.util.Date;

/**
 * Created by yamikaze on 2017/7/12.
 */
public class Message {

    private Long id;        //留言Id
    private Long uid;       //留言用户的id
    private String content; //留言内容
    private Date createTime;//留言时间
    private String ipAddress;//留言ip地址
    private Long mid;       //如果为null表示留言,不为null表示是对留言的留言
    //setter & getter方法略
}
     User.java

package org.yamikaze.model.model0;

import org.yamikaze.model.IDCard;
import org.yamikaze.model.Message;

import java.util.List;

/**
 * Created by yamikaze on 2017/7/12.
 */
public class User {

    private Long id;               //用户id
    private String username;       //用户名
    private String nickname;       //用户昵称
    private String password;       //用户密码
    private String sex;            //用户性别
    private IDCard idCard;         //用户关联的IDCard对象
    private List<Message> messages;//用户的留言

    public User(Long id,String username,String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }
    //setter & getter方法略

}
注意:记得在mybatis-config中配置别名,以及将相对应的实体类mapper文件加入到mappers中。

User表结构为:


IDCard表结构:


Message表结构:

  开始编写Mapper文件吧!

  MessageMapper文件与IDCardMapper文件略(里面只用添加一个insert方法)

   UserMapper文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.yamikaze.dao.impl.IUserDao0">

    <insert id="save" parameterType="org.yamikaze.model.model0.User0">
        insert into t_user0(username,nickname,password,sex,id)
        value (#{username},#{nickname},#{password},#{sex},#{id})
    </insert>

    <select id="load" parameterType="long" resultMap="userResult">
        select user.* from t_user0 user where user.id = #{id}
    </select>

    <resultMap id="userResult" type="User0">
        <!--如果要使用构造函数来加载对象,用这个标签并传入相应参数-->
        <constructor>
            <!--可以使用resultMap嵌套对象,也可以使用select属性指定嵌套查询-->
            <idArg column="id" javaType="long"/>
            <!--column数据库的参数名-->
            <arg column="username" javaType="string"/>
            <arg column="password" javaType="string"/>
        </constructor>
        <!--使用result来映射其他属性-->
        <!--如果数据库列名与属性名一致,可以在resultMap标签设置autoMapping为true-->
        <!--也可以指定该属性对应的javaType和数据库jdbcType-->
        <result column="nickname" property="nickname"/>
        <result column="sex" property="sex"/>
        <!--映射关联对象,这儿可以使用嵌套查询和结果嵌套-->
        <!--嵌套查询:重新发起一条sql语句查询-->
        <!--结果嵌套:将查出的结果嵌入到对象中,这儿使用第一种,因为有属性重名且没有指定别名-->
        <association property="idCard" select="selectCard" column="id"/>
        <!--集合查询 与Association一致,可以使用嵌套查询和结果查询-->
        <!--需要注意的是:要通过ofType属性指定集合里的具体类型-->
        <!--可以不指定javaType,因为Mybatis在大多数情况下会给你算出来-->
        <collection property="messages" autoMapping="true" column="id"
          javaType="ArrayList" select="selectMessage" ofType="Message">
        </collection>
    </resultMap>

    <select id="selectCard" parameterType="long" resultMap="IDCardResult">
        select * from t_id_card where uid = #{uid}
    </select>

    <resultMap id="IDCardResult" type="IDCard" autoMapping="true">
        <result property="createTime" column="create_time"/>
    </resultMap>

    <select id="selectMessage" parameterType="long" resultMap="MessageResult">
        select * from t_message where uid = #{uid}
    </select>

    <resultMap id="MessageResult" type="Message" autoMapping="true">
        <result property="createTime" column="create_time"/>
        <result property="ipAddress" column="ip_address"/>
    </resultMap>
</mapper>
测试代码(请在测试前录入相应测试数据):

public static void load() {
        InputStream is = null;
        SqlSessionFactory factory = null;
        SqlSession session = null;
        try {
            is = Resources.getResourceAsStream("mybatis-config.xml");
            factory = new SqlSessionFactoryBuilder().build(is);
            session = factory.openSession();

            User0 user = (User0)session.selectOne("load",1L);
            System.out.println(user.getSex());
            System.out.println(user.getMessages().size());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(session!=null) session.close();
        }
    }
结果:

看了userMapper的配置,我们发现有嵌套查询和结果嵌套两种方式映射。

嵌套查询会重新发sql语句查询,而结果嵌套需要我们手动为结果配置别名,比如测试的IDCard类与Message类都有no属性,那么要使用结果嵌套我们就需要这样指定别名

select card.no as card_no,message.no as message_no.......这样的方式。同时建议开启autoMapping=true,这样可以减少配置。

3、缓存配置。

在mapper映射文件中开启缓存只需要加入这一句:

<cache/>
关于cache标签:
所有 select 语句将会被缓存。默认useCache=true
所有 insert,update 和 delete 语句会刷新缓存。默认flashCache=true。
缓存会使用Least Recently Used(LRU,最近最少使用的)算法来收回。
根据时间表(比如 no Flush Interval,没有刷新间隔), 缓存不会以任何时间顺序 来刷新。
缓存会存储列表集合或对象(无论查询方法返回什么)的 1024 个引用。
缓存会被视为是 read/write(可读/可写)的缓存,意味着对象检索不是共享的,而且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。

<cache
  eviction="FIFO"
  flushInterval="60000"
  size="512"
  readOnly="true"/>
flushInterval:刷新间隔。

size:引用对象的数量,必须是整数。

readOnly是否可读可写。
eviction:回收策略,默认为LRU

当然你可以自定义缓存,使用type属性来指定。例如:

<cache type="org.yamikaze.cache.MyCache"/>
这个类必须实现 org.mybatis.cache.Cache接口,如果要向实现类传值的话,可以使用property标签,如下:

<cache type="org.yamikaze.cache.MyCache">
<property name="cacheName" value="MyCacha"/>
</cache>
注意:使用缓存不要忘了在mybatis-config.xml文件中开启全局缓存。


Mybatis常用的配置基本就这些了,因个人原因可能还有一些其他的配置没有提到的。

如果想了解Mybatis具体有哪些配置的话可以访问http://www.mybatis.org/mybatis-3/zh/index.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis是一个开源的持久化框架,可以帮助我们将数据从数据库中读取出来,然后转换为Java对象,并将Java对象写入数据库中。 在C#中使用MyBatis,需要先安装MyBatis.Net库,然后在项目中引用该库。接着,我们需要创建一个配置文件,用于配置MyBatis的数据库连接信息、SQL语句等。在配置文件中,我们需要指定一个别名,用于在程序中引用这个配置文件。 接下来,我们需要创建一个映射文件,用于将数据库中的数据映射为Java对象。在映射文件中,我们需要定义一个 resultMap,用于定义Java对象与数据库表之间的关系。我们还需要定义一个 SQL 语句,用于从数据库中读取数据,并将其转换为Java对象。 在程序中,我们需要创建一个 SqlSession 对象,用于执行SQL语句。我们可以通过SqlSession对象调用selectOne、selectList、update、delete等方法,来执行SQL语句,并将结果转换为Java对象或者操作数据库。 下面是一个简单的示例,展示了如何在C#中使用MyBatis: 1. 安装MyBatis.Net库 在Visual Studio中,选择“工具”-“NuGet包管理器”-“程序包管理器控制台”,然后输入以下命令: ``` Install-Package MyBatisNet ``` 2. 创建配置文件 在项目中创建一个名为“SqlMapConfig.xml”的文件,用于配置数据库连接信息、SQL语句等。以下是一个示例配置文件: ``` xml <?xml version="1.0" encoding="utf-8" ?> <sqlMapConfig> <database> <provider name="SqlServer" connectionString="Data Source=localhost;Initial Catalog=mydatabase;User ID=myuser;Password=mypassword;" /> </database> <sqlMap> <map resource="MyMapper.xml"/> </sqlMap> </sqlMapConfig> ``` 其中,provider元素用于指定数据库类型和连接字符串,map元素用于指定映射文件路径。 3. 创建映射文件 在项目中创建一个名为“MyMapper.xml”的文件,用于将数据库中的数据映射为Java对象。以下是一个示例映射文件: ``` xml <?xml version="1.0" encoding="utf-8" ?> <sqlMap namespace="MyMapper"> <resultMap id="MyResultMap" class="MyClass"> <result property="id" column="id"/> <result property="name" column="name"/> </resultMap> <select id="selectById" resultMap="MyResultMap"> SELECT * FROM mytable WHERE id=#id# </select> </sqlMap> ``` 其中,resultMap元素用于定义Java对象与数据库表之间的关系,select元素用于定义SQL语句。 4. 在程序中使用MyBatis 在程序中,我们需要创建一个 SqlSession 对象,用于执行SQL语句。以下是一个示例代码: ``` csharp using IBatisNet.DataMapper; using IBatisNet.DataMapper.Configuration; using IBatisNet.DataMapper.Configuration.Files; // 创建配置文件 DomSqlMapBuilder builder = new DomSqlMapBuilder(); ISqlMapper sqlMapper = builder.Configure(@"SqlMapConfig.xml"); // 执行SQL语句 MyClass obj = sqlMapper.QueryForObject<MyClass>("MyMapper.selectById", new { id = 1 }); ``` 以上是一个简单的示例,展示了如何在C#中使用MyBatis。实际上,MyBatis还有很多其他的用法和功能,需要我们在实际开发中去探索和使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值