Mybatis学习——Mybatis核心配置
MyBatis的核心配置
在使用MyBatis框架时,设计两个核心的d对象:SqlSessionFactory和SqlSession.
SqlsessionFactory
SqlSessionFactory是单个数据库映射关系经过编译后的内存镜像,其主要作用用来创建SqlSession对象,SqlSessionFactory实例对象是可以通过SqlSessionFactoryBulider对象来构建,而SqlSessionFactoryBulider对象可以通过XML文件或者Configuration实例来创建SqlSessionFactory实例,其代码如下:
//1.读取配置文件 String resource ="mybatis-config.xml";
InputStream inputStream=Resources.getResourceAsStream(resource); //2.获取会话工厂对象 SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
注意:SqlSessionFactory对象是线性安全的,它一旦被创建,在整个应用程序间都会存在,如果我们多次的创建同一个SqlSessionFactory对象,那么数据库的资源很快就会被应用完,为了解决这个问题,通常,一个数据库是建一个SqlSessionFactory对象的。
SqlSession
SqlSession对象是应用层和持久层之间进行数据库操作的一个单线程对象,其中主要作用是执行持久化操作,SqlSession对象中包含了所有执行数据库操作的方法,由于底层封装了JDBC的连接,所以可以直接使用SqlSession对象来执行已经映射的SQL语句。
注意:每一个线程都应该有自己的SqlSession实例,并且该SqlSession实例是不可共享的,同时,SqlSession是线程不安全的,因此,其使用范围最好是在一个请求中,或者一个方法中,绝对不能将其放入一个类的静态字段中,实例字段或者任何类型的管理范围中,使用完SqlSession后,要及时的关闭它,通常可以将其放入finally块中关闭。
Sqlsession sqlSession=sqlSessionFactory.openSession(); try{ //执行操作 }finally{ //关闭sqlSession sqlSession.close(); }
使用工具类来创建SqlSession对象
由于每个方法执行都需要获取配置文件,并根据配置文件的信息来构建SqlSessionFactory对象,然后创建SqlSession对象,这导致了大量重复的代码,为了简化开发,可以将重复的代码封装到一个工具类中,然后通过这个工具类来创建SqlSession
package com.itheima.util; /** * 工具类 * @author 12428 * */ import java.io.Reader; import org.apache.ibatis.io.Resources; import org.apache.ibatis.jdbc.Null; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class MyBatisUtils { private static SqlSessionFactory sqlSessionFactory=null; //获取sqlSessionFactory对象 static { try { //使用MyBatis提供的Resource类加载配置文件 Reader reader =Resources.getResourceAsReader("mybatis-config.xml"); //构建SqlSessionFactory对象 sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader); }catch(Exception e) { e.printStackTrace(); } } //获取SqlSession对象的静态方法 public static SqlSession getSession() { return sqlSessionFactory.openSession(); } }
二.配置文件
主要元素
在MyBatis核心配置文件中,<configuration>元素是配置文件的根元素,其他的元素都要在其中配置,MyBatis的配置文件mybatis-config.xml中的主要元素如下:
注意:<configuration>的子元素中必须按照由上到下的顺序进行配置,否则MyBatis在解析XML配置文件的时候会出错。
<properties>元素
该元素是一个配置属性的元素,该元素通常是用于将内部的配置外在化,既通过外部的配置来动态的替换内部定义的属性。例如,数据库的来连接属性,就可以通过Java文件中配置文件来替换,具体如下:
1.在src下创建一个db.properties属性文件,内容如下:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring
jdbc.username=root
jdbc.password=abc
2.在MyBatis配置文件mybatis-config.xml中的configuration元素中配置子元素<properties>
<properties resource="db.properties"/> //映入外部配置文件
3.修改<dataSource>配置文件中数据库连接的信息,具体如下。
<!-- 数据库连接池 --> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource>
完成了上面的配置后,dataSource中连接数据库的4个属性,就可以由db.properties文件中的对应的值来动态的替换。
由于使用properties配置文件来配置属性值可以方便的在多个配置文件中使用这些属性,并且方便日后的维护和修改,所以在实际开发中,使用properties配置文件来配置属性值是最常用的方法。
<typeHandler> 元素
MyBatis在预处理语句(PrparedStatement)中设置了一个参数或者从结果集中取出一个值时,都会使用其框架内部的注册了的typeHandler(类型处理器)进行相关的处理,typeHandler是将预处理语句中传入的参数从javaType(java类型)装换为jdbcType(JDBC)类型,或者从数据库中取出结果时将jdbcType转换为javaType类型。MyBatis框架提供了一些默认的类型转换器,如果提供的类型转换器不能满足需求时,可以自定义类型转换器,自定义类型转换器可以通过实现TypeHandler接口或者继承BaseTypeHandle类来定义。
1.注册一个类的类型处理器:
<typeHandlers> <!--以单个类的形式来配置:handler属性是用指定在程序中自定义的类型处理器类--> <typeHandler handler="com.itheima.type.CustomtypeHandler"/> </typeHandlers>
2.注册一个包中的所有类型处理器:
<typeHandlers> <!--注册一个包中所有的typeHandler,系统会在启动时会自动扫描包下的所有文件--> <package name="com.itheima.type"/> </typeHandlers>
<environments>元素
在配置文件中,<environments>元素用于对环境进行配置。MyBatis的环境配置实际上是数据源的配置,我们可以通过<environments>元素来配置多种数据源。既配置多种数据库。
使用该元素进行环境配置时的实例如下:
<!--因为一个environments元素中可以配置多个数据-库环境<environment>,default属性是指定使用哪个数据库环境,该属性值是<environment>元素的id值->
<environments default="mysql">
<!-- 配置id为mysql的数据库环境 --> <environment id="mysql">
<!-- 使用JDBC的事务管理 --> <transactionManager type="JDBC"/> <!-- 数据库连接池 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/spring"/> <property name="username" value="root"/> <property name="password" value="abc"/> </dataSource> </environment> </environments>
<environment>元素是<environments>的子元素,该元素可以有多个。在<environment>中包含了事务管理和数据源的配置信息,其中<teansactionManager>是用于配置事务管理,其中它的type属性是用于指定使用哪种事务管理器;<dataSource>是用于配置数据源,其中的type属性是用于指定使用哪种数据源。
对于数据源的配置,MyBatis框架提供了UNPOOLED,POOLED,JNDI这三种类型的数据源。
(1)UNPOOLED:配置此数据源后,在每次被请求时会打开和关闭连接,此配置适用于对性能没有要求的简单应用程序是一个很好的选择。
(2)POOLED:此数据源是利用”池“的概念将JDBC连接对象组织起来,避免了在创建新的实例时所需要初始化和认证的时间,这种方法使得并发web应用可以快速的响应,是当前流行的处理方法。
(3)JNDI:此数据源是可以在EJB或者应用服务器上使用,(是从TOMCAT内部来获取一个内置的数据库连接池)
<mappers>元素
在配置文件中,<mappers>元素是用来指定Mapper配置文件的位置,一般是使用如下四种方法引入:
1.使用类路劲引入
<mappers> <mapper resource="com/itheima/mapper/UserMapper.xml"/> </mappers>
2.使用本地文件路劲引入
<mappers> <mapper url="file:///D:/com/itheima/mapper/UserMapper.xml"/> </mappers>
3.使用接口类来引入
<mappers> <mapper class="com.itheima.mapper.UserMapper"/> </mappers>
4.使用包名来引入文件
<mappers> <package name="com.itheima.mapper"/> </mappers>
三.映射文件
映射文件是框架中的重要文件,可以说,此框架的强大之处就在于映射文件的编写上,
1.主要元素
在映射文件中,<mapper>元素是映射文件的根元素,其他元素都是它的子元素,
2.<select>元素
该元素是用于映射查询语句,它可以帮助我们从数据库中读取出数据,并组装数据库给业务开发人员
使用select元素执行查询操作非常简单,其示例如下
<select id="findCustomerById" parameterType="Integer" resultType="com.itheima.po.Customer"> select * from t_customer where id=#{id} </select>
select元素的常用属性如下:
属性 | 说明 |
id | 表示命名空间中的唯一标识符,经常和命名空间namespace一起使用,组合namespace一起使用后如果不唯一,就会抛出错误。 |
parameterType | 该属性是表示传入sql参数类的全限定名或者别名,它是一个可选属性。 |
resultType | 该属性是表示从sql语句中返回结果的类型的全限定名或者别名,如果是集合类型,那么返回的应该是集合里可以包含的类型,而不是集合本身。 |
resultMap | 该属性是表示外部resultMap的命名引用,返回时可以使用resultMap或者resultType |
flushCache | 表示在调用SQL语句后,是否清除缓之前查询的本地缓存和二级缓存,默认时false |
useCache | 用于控制二级缓存的开启和关闭,其值为布尔型,默认为true,表示将查询结果放在二级缓存里 |
timeout | 用于设置超时参数,单位为秒,超时时将抛出异常 |
fetchSize | 获取记录的总条数设置,其默认值是unset(依赖于驱动) |
statementType | 用于设置MyBatis使用哪个JDBC的Statement工作。 |
resultSetType | 表示结果集的类型 |
3<insert>元素
insert元素是用于映射插入语句,在执行完元素中定义的SQL语句后,就会返回一个表示插入记录数的整数,insert元素的配置实例如下
<insert id="addCustomer" parameterType="com.itheima.po.Customer" flushCache="true" statmentType="PREPARED" keyProperty="" keyColumn="" useGeneratedKeys="" timeout="20"> </insert>
insert元素的属性大部分和select相同,但是它由三个特定是属性,这三个属性如下:
属性 | 说明 |
keyProperty | (仅对insert和update有用)此属性的作用是将插入或者更新操作时的返回值赋给PO类的某个属性,通常会设置为主键对应的属性,如果需要设置联合主键,可以在多个值之间用逗号分开 |
keyColumn | (仅对insert和update有用)此属性的作用是用于设置第几行是主键,当主键列不是表中的第一列是,是需要设置这个属性,在需要使用主键联合时,值可以使用逗号分开 |
useGeneratedKeys | (仅对insert和update有用)此属性会使MyBatis使用JDBC的getGeneratedKeys()方法来获取由数据库内部产生的主键,如MYSql和sql Server等自动生成的主键 |
执行查询操作后,很多时候我们需要返回插入成功的数据生成的主键,此时就可以通过上面所讲解的3个属性来实现。
当使用的数据库支持自动增长时,我们可以通过keyproperty属性来指定PO类的某个属性接受主键的返回值,同时设置useGeneratedKeys的属性值为true,其使用如下:
<insert id="addCustomer" parameterType="com.itheima.po.Customer" keyProperty="id" useGeneratedKeys="true"> insert into t_customer(username,jobs,phone) values(#{username},#{jobs},#{phone}) </insert>
使用以上的配置后执行插入操作后,就会返回插入成功的行数,以及插入行的主键值,为了验证配置,可以使用如下代码测试:
@Test public void addCustomer(){ //获取SqlSession对象 SqlSession sqlSession=MyBatisUtis.getSession(); Customer customer=new Customer(); customer.setUsername("rose"); customer.setJobs("student"); customer.setPhone("11111111"); int rows=sqlSession.insert("som.itheima.mapper.CustomerMapper.addCustomer",customer); //输出插入数据的主键 System.out.println(customer.getId()); if(rows>0){ system.out.println("您成功插入了"+rows+"行数据!"); }else{ system.out.println("插入失败!"); } //执行提价事务 sqlSession.commit(); //关闭资源 sqlSession.close(); }
当数据库不可以支持自动增长时,如Oracle,或者自动增长的数据库取消了自动增长的规则时,可以使用MyBatis提供的另一种方法来自定义生成主键,具体配置如下:
<insert id="addCustomer" parameterType="com.itheima.po.Customer" > <selectKey keyProperty="id" resultType="Integer" order="BEFORE"> select if(max(id) is null,1, max(id)+1) as newId from t_customer </selectKey> insert into t_customer(id,username,jobs,phone) values(#{id},#{username},#{jobs},#{phone}) </insert>
在执行上面代码时,会先执行<selectKey>中的语句,他会通过自定义的语句来设置主键的值,如果t_customer表中的没有记录,就将id的值设置为1,如果有id值,就将id值加上1,作为新的主键,然后在调用插入语句。
selectKey可以设置的属性如下:
<selectKey keyProperty="id" resultType="Integer" order="BEFORE" statmentType="PREPARED">
</selectKey>
order属性可以被设置为BEFORE或者AFTER,如果设置为BREFORE,那么它会先执行<selectKey>中的配置来设置主键,然后执行插入语句,如果设置为AFTER,那么它会先执行插入语句,然后再执行<selectKey>中的配置内容。
4.<update>和<delete>元素
这两个元素的执行非常简单,它们的配置也基本相同,与<insert>元素一样,这里两个元素在执行后,也会返回一个表示影响记录条数的整数。
5.<sql>元素
<sql>元素是用于定义可重用的SQL片段,然后在其他的语句中引用这一片代码,例如定义一个包含了id,username,jobs,phone字段的代码片段如下:
<sql id="customerColumns">id,username,jobs,phone</sql>
引用此代码如下:
<select id="findCustomerById" parameterType="Integer" resultType="com.itheima.po.Customer"> select <include refid="customerColumns"/> from t_customer where id=#{id} </select>
使用<include>元素的refid属性可以引用自定义的代码片段,refid属性值自定义代码段的id值。
6.<resultMap>元素
该元素是用于配置查询返回的结果与JavaBean类之间的映射关系,是MyBatis中最强大的元素。它的主要作用是定义映射规则,级联的更新,以及定义类型转换器。
<resultMap>元素包含了一些子元素,他的结构如下:
<!--resultMap元素的结构 --> <resultMap type="" id=""> <!--类在实例化时,用来注入结果到构造方法中--> <constructor> <idArg/> <!--ID参数:标记结果作为Id--> <arg/> <!--注入到构造方法中的一个普通结果--> </constructor> <id/> <!--用来表示哪个列示主键--> <result> <!--注入到字段或者JavaBean属性的普通结果--> <association property=""/> <!--用于一对一关联--> <collection property=""/> <!--用于一对多关联--> <discriminator javaType=""> <case value=""/> <!--基于某些值的结果映射--> </discriminator> </resultMap>
该元素的type属性是表示需要映射的POJO,id属性是这个resultMap的唯一标识,它的子元素<constructor>用于配置构造方法,当一个POJO中未定义无参数的构造方法时,就可以使用<constructor>配置。子元素<id>是用于表示哪个键是主键,而<result>是用于表示普通POJO和数据表中普通列的映射关系,<association>和<collection>用于配置处理多表时的关联关系。而<discriminator>是用于处理一个单独的数据库查询返回很多不同数据类型结果集的情况。
在默认的情况下,MyBatis程序在运行时会自动的将查询到 的结果和需要返回的对象的属性进行匹配复制(需要表中的列和对象的属性名完全一致。然而,在现实中,数据表中的列和需要返回的对象属性可能并不是完全一样,这时,就可以使用该元素进行处理。