1.编写mybatis.xml文件
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><!-- 配置 mybatis 的环境 --><environments default="mysql"><!-- 配置 mysql 的环境 --><environment id="mysql"><!-- 配置事务的类型 --><transactionManager type="JDBC"></transactionManager><!-- 配置连接数据库的信息:用的是数据源(连接池) --><dataSource type="POOLED"><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/ee50"/><property name="username" value="root"/><property name="password" value="1234"/></dataSource></environment></environments><!-- 告知 mybatis 映射配置的位置 --><mappers><mapper resource="com/itheima/dao/IUserDao.xml"/></mappers></configuration>
配置顺序
-properties(属性) --property-settings(全局配置参数) --setting-typeAliases(类型别名) --typeAliase --package-typeHandlers(类型处理器)-objectFactory(对象工厂)-plugins(插件)-environments(环境集合属性对象) --environment(环境子属性对象) ---transactionManager(事务管理) ---dataSource(数据源)-mappers(映射器) --mapper --package
2.使用mybatis crud基本操作步骤
//1.读取配置文件InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");//2.创建 SqlSessionFactory 的构建者对象SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();//3.使用构建者创建工厂对象 SqlSessionFactorySqlSessionFactory factory = builder.build(in);//4.使用 SqlSessionFactory 生产 SqlSession 对象SqlSession session = factory.openSession();//5.使用 SqlSession 创建 dao 接口的代理对象IUserDao userDao = session.getMapper(IUserDao.class);//6.使用代理对象执行查询所有方法List<User> users = userDao.findAll();
3.mybatis的注解
在使用基于注解的 Mybatis 配置时,请移除 xml 的映射配置(IUserDao.xml).
4.#{}与${}的区别
#{}表示一个占位符号通过#{}可以实现 preparedStatement 向占位符中设置值,自动进行 java 类型和 jdbc 类型转换,#{}可以有效防止 sql 注入。 #{}可以接收简单类型值或 pojo 属性值。 如果 parameterType 传输单个简单类型值,#{}括号中可以是 value 或其它名称。${}表示拼接 sql 串通过${}可以将 parameterType 传入的内容拼接在 sql 中且不进行 jdbc 类型转换, ${}可以接收简单类型值或 pojo 属性值,如果 parameterType 传输单个简单类型值,${}括号中只能是 value。
5.resultMap 结果类型
resultMap 标签可以建立查询的列名和实体类的属性名称不一致时建立对应关系。从而实现封装。 在 select 标签中使用 resultMap 属性指定引用即可。同时 resultMap 可以实现将查询结果映射为复杂类型的 pojo,比如在查询结果映射对象中包括 pojo 和 list 实现一对一查询和一对多查询。
<!-- 建立 User 实体和数据库表的对应关系 type 属性:指定实体类的全限定类名 id 属性:给定一个唯一标识,是给查询 select 标签引用用的。--><resultMap type="com.itheima.domain.User" id="userMap">• <id column="id" property="userId"/>• <result column="username" property="userName"/>• <result column="sex" property="userSex"/>• <result column="address" property="userAddress"/>• <result column="birthday" property="userBirthday"/></resultMap>id 标签:用于指定主键字段result 标签:用于指定非主键字段column 属性:用于指定数据库列名property 属性:用于指定实体类属性
<!-- 配置查询所有操作 -->
<select id="findAll" resultMap="userMap">
select * from user
</select>
6.mybatis数据库连接池
7.生命周期
7.1 SqlSessionFactoryBuilder
SqlSessionFactoryBuilder 作用在于创建 SqlSessionFactory ,创建成功后,SqlSessionFactoryBuilder 就失去了作用,所以它只能存在于创建 Sq!SessionFactory 的方法中,而不要让其长期存在。
7.2 SqlSessionFactory
SqlSessionFactory 可以被认为是 个数据库连接池,它的作用是创建 SqlSession 接口对象。因为 MyBatis 本质就是 Java 数据库的操作,所以 SqlSessionFactory 的生命周期存在于整个 MyBatis 应用之中,所以 旦创建了 SqlSessionFactory 就要长期保存它,直至不再使用 MyBatis 应用,所以可以认为 SqlSessionFactory 的生命周期就等同于 MyBati应用周期。 由于 sqlSessionFactory 个对数据库的连接池,所以它占据着数据库的连接资源。如果创建多个 SqlSessionFactory ,那么就存在多个数据库连接池,这样不利于对数据库资源的控制,也会导致数据库连接资源被消耗光,出现系统密机等情况,所以尽量避免发生这样的情况。因此在 般的应用中我 往往希SqlSessionFactory 作为 个单例,让它在应用中被共享。
7.3 SqlSession
如果说 SqlSes sionFactory 相当于数据库连接池,那么 SqlSession 就相 当于一个数据库连接( Connection 象) ,你可以在一个事务里面执行多条 QL ,然后通过它的 commitrollback 等方法 提交或者回滚事务。所以它应该存活在 个业务请求中,处理完整个请求后,应该关闭这条连接,让它归还给 SqlSessionFactory 否则数据库资源就很快被耗费精光,系统就会瘫痪,所以用 可... catch .. . finally ...语句来保证其正确关闭。
7.4 Mapper
Mapper 是一个接口,它由 Sq!Session 所创建,所以它的最大生命周期至多和 Sq!Session保持 一致,尽管它很好用,但是由于 SqlSession 关闭,它的数据库连接资源也会消失,所以它的生命周期应该小于等于 Sq!Se ssion 的生命周期 Mapper 表的是 个请求中的业务处理,所以它应该在一个请求中,一旦处理完了相关的业务,就应该废弃它。
8.两种发送 SQL 方式
一种用 SqlSession直接发送,另外 种通过 SqlSessio 获取 Mapper 接口再发送。笔者建议采用 SqlSession 获取Mapper 的方式,理由如下使用 Mapper 接口编程可以消除 SqlSession 带来的功能性代码,提高可读性,而 SqlSession 发送 SQL 需要一个 SQL id 去匹配 SQL ,比较晦涩难懂。使用 Mapper接口 roleMapper.getRole(lL)则 是完全面向对象的语言 更能体现业务的逻辑。使用 Mapper.getRole( 1 )方式, IDE 会提示错误和校验,而使用sqlSess on. electOne(“getRole”, lL )语法,只有在运行中才能知道是否会产生错误。
9.settings 设置
settings是MyBatis 最复杂的配置,它能深刻影响 MyBatis 底层的运行,但是在大部份情况下MyBatis 配置 使用默认值便可以运行,所以在大部分情况下不需要大量配置它,只需要修改一些常用的规 即可 比如自动映射、驼峰命名映射、级联规则、 是否启动缓存、执行器(Executor )类型等 setting 配置项说明 如表.....
10.environments (运行环境)
10.1 事务管理器(transactionManager)
MyBatis Transaction 提供了两个实现类: JdbcTransaction和ManagedTransaction,于是它对应 两种工厂 JdbcTransactionFactory和ManagedTransactionFactory 这个工厂需要实 TransactionFactory 接口 ,通过它们会生成对应 Transaction 象。于是可以把事务管理器配置成为以下两种方式:
<transactionManager type= ” JDBC ” /><transactionManager type= ” MANAGED '’/>
• JDBC 使用 JdbcTransactionFactory 生成的 JdbcTransaction 象实现。它是以 JDBC的方式对数据库的提交和回滚进行操作。 • MANAGED 使用 managedTransactionFactory 生成的 ManagedTransaction 象实现。它的提交和回滚方法不用任何操作,而是把事务交给容器处理。在默认情况下,它会关闭连接,然而 些容器并不希望这样,因 需要将 closeConnection 属性设置为false 来阻止它默认的关闭行为。
也可以自定义transactionManager。
10.2 数据源(datasource)
<dataSource type=”UN POOLED”><dataSource type= ” POOLED”><dataSource type= ” JNDI ” >
POOLED 数据源 POOLED 用“池”的概念将 JDBC Connection 对象组织起来 它开始会有一些空置,并且已经连接好的数据库连接,所以请求时 无须再建立和验证,省去了新的连接实例时所必需的初始化和认证时间。它还控制最大连接数,避免过多的连接导致系统瓶颈。 除了 UNPOOLED 下的属性外,会有更多属性用来配置 POOLED 的数据源: • poolMax mumActiveConnections 是在任意时间都存在的活动( 也就是正在使用)连接数量,默认值为 10 • poolMax murnldleConnections 是任意时间可能存在的空闲连接数。 • poolMaximumCheckoutTime 在被强制返回之前,池中连接被检出( checked out )的时间,默认值为20000 毫秒( 20 秒)。 • poolTimeToWait 个底层设置,如果获取连接花费相当长的时间,它会给连接池打印状态日志 并重新尝试获取 个连接(避免在误配置的情况下一直失败,默认值为 20 000 毫秒(即 20 秒)。 • poolPingQuery 发送到数据库的侦测查询,用来检验连接是否 在正常工作秩序,并准备接受请求。默认是“NO PING QUERY SET ”,这会导致多数数据库驱动失败时带有一个恰当的错误消息。
• poolPingEnabled 为是否启用侦测查询。若开启,也必须使用一个可执行的 SQL句设置 poo!PingQuery 属性(最好是 个非常快的 SQL) ,默认值为 false • poo!PingConnectionsNotUsedFor 为配置 poo!PingQuery 使用频度。这可以被设置匹配具体的数据库连接超时时间,来避免不必要的侦测,默认值为 0即所有连接每一时刻都被侦测一一仅 poo!PingEnabled为true 适用。
11. PageHelper
11.1 导入依赖
<dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>最新版本</version></dependency>
11.2 配置
在 MyBatis 配置 xml 中配置拦截器插件
<plugins> <!-- com.github.pagehelper为PageHelper类所在包名 --> <plugin interceptor="com.github.pagehelper.PageInterceptor"> <!-- 使用下面的方式配置参数,后面会有所有的参数介绍 --> <property name="param1" value="value1"/> </plugin></plugins>
在 Spring 配置文件中配置拦截
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 注意其他配置 --> <property name="plugins"> <array> <bean class="com.github.pagehelper.PageInterceptor"> <property name="properties"> <!--使用下面的方式配置参数,一行配置一个 --> <value> params=value1 </value> </property> </bean> </array> </property></bean>
分页插件参数介绍
1. helperDialect :分页插件会自动检测当前的数据库链接,自动选择合适的分页方式。 你可以配置helperDialect 属性来指定分页插件使用哪种方言。配置时,可以使用下面的缩写值:oracle , mysql , mariadb , sqlite , hsqldb , postgresql , db2 , sqlserver , informix , h2 , sqlserver2012 , derby特别注意:使用 SqlServer2012 数据库时,需要手动指定为 sqlserver2012 ,否则会使用 SqlServer2005 的方式进行分页。你也可以实现 AbstractHelperDialect ,然后配置该属性为实现类的全限定名称即可使用自定义的实现方法。2. offsetAsPageNum :默认值为 false ,该参数对使用 RowBounds 作为分页参数时有效。 当该参数设置为true 时,会将 RowBounds 中的 offset 参数当成 pageNum 使用,可以用页码和页面大小两个参数进行分页。3. rowBoundsWithCount :默认值为 false ,该参数对使用 RowBounds 作为分页参数时有效。 当该参数设置为 true 时,使用 RowBounds 分页会进行 count 查询。4. pageSizeZero :默认值为 false ,当该参数设置为 true 时,如果 pageSize=0 或者 RowBounds.limit =0 就会查询出全部的结果(相当于没有执行分页查询,但是返回结果仍然是 Page 类型)。5. reasonable :分页合理化参数,默认值为 false 。当该参数设置为 true 时, pageNum<=0 时会查询第一页, pageNum>pages (超过总数时),会查询最后一页。默认 false 时,直接根据参数进行查询。6. params :为了支持 startPage(Object params) 方法,增加了该参数来配置参数映射,用于从对象中根据属性名取值, 可以配置 pageNum,pageSize,count,pageSizeZero,reasonable ,不配置映射的用默认值, 默认值为pageNum=pageNum;pageSize=pageSize;count=countSql;reasonable=reasonable;pageSizeZero=pageSizeZero。7. supportMethodsArguments :支持通过 Mapper 接口参数来传递分页参数,默认值 false ,分页插件会从查询方法的参数值中,自动根据上面 params 配置的字段中取值,查找到合适的值时就会自动分页。 使用方法可以参考测试代码中的 com.github.pagehelper.test.basic 包下的 ArgumentsMapTest 和ArgumentsObjTest 。8. autoRuntimeDialect :默认值为 false 。设置为 true 时,允许在运行时根据多数据源自动识别对应方言的分页 (不支持自动选择 sqlserver2012 ,只能使用 sqlserver ),用法和注意事项参考下面的场景五。9. closeConn :默认值为 true 。当使用运行时动态数据源或没有设置 helperDialect 属性自动获取数据库类型时,会自动获取一个数据库连接, 通过该属性来设置是否关闭获取的这个连接,默认 true 关闭,设置为false 后,不会关闭获取的连接,这个参数的设置要根据自己选择的数据源来决定。
PageHelper.startPage 静态方法调用(重点)
这种方式是我们要掌握的 在你需要进行分页的 MyBatis 查询方法前调用PageHelper.startPage 静态方法即可,紧 跟在这个方法后的第一个MyBatis 查询方法会被进行分页
//获取第1页,10条内容,默认查询总数countPageHelper.startPage(1, 10)//紧跟着的第一个select方法会被分页List<Country> list = countryMapper.selectIf(1)
12. 动态sql
动态 SQL 之<where>
<!-- 根据用户信息查询 --><select id="findByUser" resultType="user" parameterType="user"> <include refid="defaultSql"></include> <where> <if test="username!=null and username != '' ">and username like #{username}</if> <if test="address != null">and address like #{address}</if> </where></select>
动态标签之<foreach>标签
public class QueryVo implements Serializable { private List<Integer> ids; } List<User> findInIds(QueryVo vo);
<!-- 查询所有用户在 id 的集合之中 --><select id="findInIds" resultType="user" parameterType="queryvo"> <!-- select * from user where id in (1,2,3,4,5); --> <include refid="defaultSql"></include> <where> <if test="ids != null and ids.size() > 0"> <foreach collection="ids" open="id in ( " close=")" item="uid" separator=",">#{uid} </foreach> </if> </where></select>SQL 语句:select 字段 from user where id in (?)<foreach>标签用于遍历集合,它的属性:collection:代表要遍历的集合元素,注意编写时不要写#{} open:代表语句的开始部分 close:代表结束 item:代表遍历集合的每个元素,生成的变量名 sperator:代表分隔符