mybatis的一些重要配置
1、全局配置文件
<?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> <!-- 1、mybatis 可以使用 properties 来引入外部 properties 配置文件的内容 resource: 引入类路径下的资源 url: 引入网络路径或者磁盘路径下的资源 --> <properties resource="dbconfig.properties"></properties> <!-- 2、settings 包含很多重要的设置项 setting: 用来设置每一个设置项 name: 设置项名 value: 设置项取值 --> <settings> <setting name="mapUnderscoreToCamelCase" value="true"/> <setting name="jdbcTypeForNull" value="NULL"/> <!-- 显式的指定每一个我们需要更改的配置的值,即使它是默认的。防止版本更新带来的问题 --> <setting name="cacheEnabled" value="true"/> <setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="false"/> </settings> <!-- 3、typeAliases: 别名处理器:可以为我们的 java 类型起别名 别名不区分大小写 --> <typeAliases> <!-- 1、typeAlias: 为某个 java 类型起别名 type: 指定要起别名的类型全类名,默认别名就是类名小写:employee alias: 指定新的别名 --> <!--<typeAlias type="com.mgy.mybatis.bean.Employee" alias="empl" />--> <!-- 2、package: 为某个报下的所有类批量起别名 name: 指定包名(为当前包以及下面所有的后代的每一个类都起一个默认别名(类名小写)) --> <package name="com.mgy.mybatis.bean"/> <!-- 3、批量起别名的情况下,使用 @Alias 注解为某个类型指定新的别名 --> </typeAliases> <!-- 4、environments: 环境们,mybatis 可以配置多种环境,default 指定使用某种环境。可以达到快速切换环境 environment: 配置一个具体的环境信息,必须有两个标签,id 代表当前环境的唯一标识 transactionManager: 事务管理器 type: 事务管理器的类型:JDBC(JdbcTransactionFactory)|MANAGED(ManagedTransactionFactory) 自定义事务管理器:实现 TransactionFactory 接口,type 指定为全类名 dataSource: 数据源 type: 数据源类型:UNPOOLED(UnpooledDataSourceFactory) |POOLED(PooledDataSourceFactory) |JNDI(JndiDataSourceFactory) 自定义数据源:实现 DataSourceFactory 接口,type 是全类名 --> <environments default="dev_mysql"> <environment id="dev_mysql"> <transactionManager type="JDBC" /> <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> </environment> <environment id="dev_oracle"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="${orcl.driver}" /> <property name="url" value="${orcl.url}" /> <property name="username" value="${orcl.username}" /> <property name="password" value="${orcl.password}" /> </dataSource> </environment> </environments> <!-- 5、databaseIdProvider: 支持多数据库厂商的 type="DB_VENDOR": VendorDatabaseIdProvider 作用就是得到数据库厂商的标识(驱动 getDatabaseProductName()) MySQL、Oracle、SQL Server ... --> <databaseIdProvider type="DB_VENDOR"> <!-- 为不同的数据库厂商起别名 --> <property name="MySQL" value="mysql"/> <property name="Oracle" value="oracle"/> <property name="SQL Server" value="sqlserver"/> </databaseIdProvider> <!-- 将我们写好的sql映射文件(EmployeeMapper.xml)一定要注册到全局配置文件(mybatis-config.xml)中 --> <!-- 6、mappers: 将 sql 映射注册到全局配置中 --> <mappers> <!-- mapper: 注册一个 sql 映射 注册配置文件 resource: 引用类路径下的 sql 映射文件 mybatis/mapper/EmployeeMapper.xml url: 引用网络路径或磁盘路径下的 sql 映射文件 file:///var/mappers/AuthorMapper.xml 注册接口 class: 引用(注册)接口 1、有 sql 映射文件,映射文件名必须和接口同名,并且放在与接口同一目录下; 2、没有 sql 映射文件,所有的 sql 都是利用注解写在接口上 推荐: 比较重要的、复杂的 Dao 接口,我们写在 sql 映射文件上 不重要的、简单的 Dao 接口,为了开发快速可以使用注解 --> <!-- <mapper resource="com.mgy.mybatis.dao/EmployeeMapper.xml" />--> <!-- <mapper class="com.mgy.mybatis.dao.EmployeeMapper" />--> <!-- <mapper class="com.mgy.mybatis.dao.EmployeeMapperAnnotation" />--> <!-- 批量注册 --> <package name="com.mgy.mybatis.dao"/> </mappers> </configuration>
2、简单SQL语句操作
<?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"> <!-- namespace: 名称空间;指定为接口的全类名 id: 唯一标识 resultType: 返回值类型 #{id}: 从传递过来的参数中取出 id 值 Employee getEmpById(Integer id); --> <mapper namespace="com.mgy.mybatis.dao.EmployeeMapper"> <!-- eviction: 缓存的回收策略 • LRU – 最近最少使用的:移除最长时间不被使用的对象。 • FIFO – 先进先出:按对象进入缓存的顺序来移除它们。 • SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。 • WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。 • 默认的是 LRU。 flushInterval:缓存刷新间隔 缓存多长时间清空一次,默认不清空,设置一个毫秒值 readOnly:是否只读 true:只读 ==> mybatis 认为所有从缓存中获取数据的操作都是只读操作,不会修改数据 mybatis 为了加快获取速度,直接就会将数据在缓存中的引用交给用户 false: 非只读 ==> mybatis 觉得获取的数据可能会被修改 mybatis 会利用序列化 & 反序列化的技术克隆一份新的数据给你 size:缓存存放多少元素 type: 指定自定义缓存的全类名 实现 Cache 接口即可 --> <!--<cache eviction="FIFO" flushInterval="60000" readOnly="false" size="1024"></cache>--> <!-- 使用第三方缓存 --> <cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache> <!-- @MapKey("lastName") Map<String, Employee> getEmpByLastNameLikeReturnMap(String lastName); --> <select id="getEmpByLastNameLikeReturnMap" resultType="com.mgy.mybatis.bean.Employee"> select * from tbl_employee where last_name like #{lastName} </select> <!--返回一条记录的 map,key 就是列名,值就是对应的值--> <!--Map<String, Object> getEmpByIdReturnMap(Integer id);--> <select id="getEmpByIdReturnMap" resultType="map"> select * from tbl_employee where id = #{id} </select> <!--List<Employee> getEmpByLastNameLike(String lastName);--> <!-- resultType: 如果返回的是一个集合,要写集合中元素的类型 --> <select id="getEmpByLastNameLike" resultType="com.mgy.mybatis.bean.Employee"> select * from tbl_employee where last_name like #{lastName} </select> <!--Employee getEmpByMap(Map<String, Object> map);--> <select id="getEmpByMap" resultType="com.mgy.mybatis.bean.Employee"> select * from ${tableName} where id = ${id} and last_name = #{lastName} </select> <!--Employee getEmpByIdAndLastName(Integer id, String lastName);--> <select id="getEmpByIdAndLastName" resultType="com.mgy.mybatis.bean.Employee"> select * from tbl_employee where id = #{id} and last_name = #{lastName} </select> <select id="getEmpById" resultType="com.mgy.mybatis.bean.Employee"> select * from tbl_employee where id = #{id} </select> <select id="getEmpById" resultType="com.mgy.mybatis.bean.Employee" databaseId="mysql" useCache="true"> select * from tbl_employee where id = #{id} </select> <select id="getEmpById" resultType="com.mgy.mybatis.bean.Employee" databaseId="oracle" > select EMPLOYEE_ID id, LAST_NAME lastName, EMAIL email from tbl_employee where id = #{id} </select> <!--Long addEmp(Employee employee);--> <!-- parameterType:参数类型,可以省略 获取自增主键的值: mysql 支持自增主键,自增主键值的获取,mybatis 也是利用 statement.getGeneratedKeys(); useGeneratedKeys="true"; 使用自增主键获取主键值策略 keyProperty: 指定对应的主键属性,也就是 mybatis 获取到主键值以后,将这个值封装给 javaBean 的那个属性 --> <insert id="addEmp" parameterType="com.mgy.mybatis.bean.Employee" useGeneratedKeys="true" keyProperty="id" databaseId="mysql" flushCache="true"> insert into tbl_employee(last_name, email, gender) values (#{lastName}, #{email}, #{gender}) </insert> <!-- 获取非自增主键的值: Oracle 不支持自增:Oracle 使用序列来模拟自增; 每次插入的数据的主键是从序列中拿到的值;如何获取到这个值 --> <insert id="addEmp" databaseId="oracle"> <!-- keyProperty: 查出的主键值封装给 javaBean 的哪个属性 order="BEFORE": 当前 sql 在插入 sql 之前运行 AFTER: 当前 sql 在插入之后运行 resultType:查出的数据的返回值类型 BEFORE 运行顺序: 先运行 selectKey 查询 id 的 sql,查出 id 值封装给 JavaBean 的 id 属性 再运行插入的 sql,就可以取出 id 属性对应的值 AFTER 运行顺序: 先运行插入的 sql(从序列中取出新值作为 id) 再运行 selectKey 查询 id 的 sql --> <selectKey keyProperty="id" order="BEFORE" resultType="Integer"> <!-- 编写查询主键的 sql 语句 --> <!-- BEFORE --> select EMPLOYEES_SEQ.nextval from dual <!-- AFTER: select EMPLOYEES_SEQ.currval from dual --> </selectKey> <!-- 插入时的主键是从序列中拿到的 --> <!-- BEFORE: --> insert into employees(employee_id, last_name, email, gender) values (#{id}, #{lastName}, #{email<!--, jdbcType=NULL-->}, #{gender}) <!-- AFTER: insert into employees(employees_id, last_name, email, gender) values(employees_seq.nextval, #{lastName}, #{email}, #{gender}) --> </insert> <!--boolean updateEmp(Employee employee);--> <update id="updateEmp"> update tbl_employee set last_name = #{lastName}, email = #{email}, gender = #{gender} where id = #{id} </update> <!--void deleteEmpById(Integer id);--> <delete id="deleteEmpById"> delete from tbl_employee where id = #{id} </delete> </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="com.mgy.mybatis.dao.DepartmentMapper"> <!-- 引用缓存:namespace ==> 指定和哪个名称空间下的缓存一样 --> <cache-ref namespace="com.mgy.mybatis.dao.EmployeeMapper"/> <!--Department getDeptById(Integer id);--> <select id="getDeptById" resultType="com.mgy.mybatis.bean.Department"> select id, dept_name departmentName from tbl_dept where id = #{id}; </select> <!-- public class Department { private Integer id; private String departmentName; private List<Employee> emps; did dept_name || eid last_name email gender --> <!-- 嵌套结果集的方式,使用 collection 标签定义关联的集合类型的属性封装规则 --> <resultMap id="MyDept" type="com.mgy.mybatis.bean.Department"> <id column="did" property="id" /> <result column="dept_name" property="departmentName" /> <!-- collection: 定义关联集合类型的属性的封装规则 ofType: 指定集合里面元素的类型 --> <collection property="emps" ofType="com.mgy.mybatis.bean.Employee"> <!-- 定义这个集合中元素的封装规则 --> <id column="eid" property="id" /> <result column="last_name" property="lastName" /> <result column="email" property="email" /> <result column="gender" property="email" /> </collection> </resultMap> <!--Department getDeptByIdPlus(Integer id);--> <select id="getDeptByIdPlus" resultMap="MyDept"> select d.id did, d.dept_name dept_name, e.id eid, e.last_name last_name, e.email email, e.gender gender from tbl_dept d left join tbl_employee e on d.id = e.d_id where d.id = #{id} </select> <!-- collection: 分段查询 --> <resultMap id="MyDeptStep" type="com.mgy.mybatis.bean.Department"> <id column="id" property="id" /> <result column="dept_name" property="departmentName" /> <collection property="emps" select="com.mgy.mybatis.dao.EmployeeMapperPlus.getEmpsByDeptId" column="{deptId=id}" fetchType="eager"> </collection> </resultMap> <!--Department getDeptByIdStep(Integer id);--> <select id="getDeptByIdStep" resultMap="MyDeptStep"> select id, dept_name from tbl_dept where id = #{id} </select> <!-- 扩展:多列的值传递过去: 将多列的值封装在 map 中传递过去: column="{key1=column1, key2=column2}" fetchType="lazy": 表示使用延时加载 - lazy:延时加载 - eager: 立即加载 --> </mapper>
3、mybatis的逆向工程
① 添加依赖
<!-- mybatis 的代码生成器 --> <dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.3.2</version> </dependency> <!-- mybatis-generator自动生成代码插件 --> <dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.2</version> </dependency>
② 生成代码的配置文件 mbg.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <!-- targetRuntime="MyBatis3Simple":生成简单版的CRUD MyBatis3:豪华版 --> <context id="DB2Tables" targetRuntime="MyBatis3"> <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver" connectionURL="jdbc:mysql://127.0.0.1:3306/mybatis?allowMultiQueries = true&useUnicode=true&characterEncoding=UTF-8&userSSL=false&serverTimezone=GMT%2B8" userId="root" password="root"> </jdbcConnection> <!-- java 类型处理器 --> <javaTypeResolver> <property name="forceBigDecimals" value="false"/> </javaTypeResolver> <!-- javaModelGenerator:指定 javaBean 的生成策略 targetPackage:目标包名 targetProject:目标工程 --> <javaModelGenerator targetPackage="com.mgy.mybatis.bean" targetProject=".\src\main\java"> <property name="enableSubPackages" value="true"/> <property name="trimStrings" value="true"/> </javaModelGenerator> <!-- sqlMapGenerator: sql 映射生成策略 --> <sqlMapGenerator targetPackage="com.mgy.mybatis.dao" targetProject=".\src\main\java"> <property name="enableSubPackages" value="true"/> </sqlMapGenerator> <!-- javaClientGenerator: 指定 mapper 接口所在的位置 --> <javaClientGenerator type="XMLMAPPER" targetPackage="com.mgy.mybatis.dao" targetProject=".\src\main\java"> <property name="enableSubPackages" value="true"/> </javaClientGenerator> <!-- 指定要逆向分析哪些表:根据表要创建 javaBean --> <table tableName="tbl_dept" domainObjectName="Department"></table> <table tableName="tbl_employee" domainObjectName="Employee"></table> </context> </generatorConfiguration>
4、mybatis整合spring的配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- Spring希望管理所有的业务逻辑组件,等。。。 --> <context:component-scan base-package="com.atguigu.mybatis"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /> </context:component-scan> <!-- 引入数据库的配置文件 --> <context:property-placeholder location="classpath:dbconfig.properties" /> <!-- Spring用来控制业务逻辑。数据源、事务控制、aop --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="jdbcUrl" value="${jdbc.url}"></property> <property name="driverClass" value="${jdbc.driver}"></property> <property name="user" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!-- spring事务管理 --> <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 开启基于注解的事务 --> <tx:annotation-driven transaction-manager="dataSourceTransactionManager"/> <!-- 整合mybatis 目的:1、spring管理所有组件。mapper的实现类。 service==>Dao @Autowired:自动注入mapper; 2、spring用来管理事务,spring声明式事务 --> <!--创建出SqlSessionFactory对象 --> <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <!-- configLocation指定全局配置文件的位置 --> <property name="configLocation" value="classpath:mybatis-config.xml"></property> <!--mapperLocations: 指定mapper文件的位置--> <property name="mapperLocations" value="classpath:mybatis/mapper/*.xml"></property> </bean> <!--配置一个可以进行批量执行的sqlSession --> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactoryBean"></constructor-arg> <constructor-arg name="executorType" value="BATCH"></constructor-arg> </bean> <!-- 扫描所有的mapper接口的实现,让这些mapper能够自动注入; base-package:指定mapper接口的包名 --> <mybatis-spring:scan base-package="com.atguigu.mybatis.dao"/> <!-- <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.atguigu.mybatis.dao"></property> </bean> --> </beans>
5、oracle 存储过程的使用
create or replace procedure hello_test( p_start in int, p_end in int, p_count out int, p_emps out sys_refcursor ) as begin select count(*) into p_count from employees; open p_emps for select * from (select rownum rn, e.* from employees e where rownum <= p_end) where rn >= p_start; end hello_test;
<!-- public void getPageByProcedure(); 1、使用select标签定义调用存储过程 2、statementType="CALLABLE":表示要调用存储过程 3、{call procedure_name(params)} --> <select id="getPageByProcedure" statementType="CALLABLE" databaseId="oracle"> {call hello_test( #{start,mode=IN,jdbcType=INTEGER}, #{end,mode=IN,jdbcType=INTEGER}, #{count,mode=OUT,jdbcType=INTEGER}, #{emps,mode=OUT,jdbcType=CURSOR,javaType=ResultSet,resultMap=PageEmp} )} </select>
** * 封装分页查询数据 * @author lfy * */ public class OraclePage { private int start; private int end; private int count; private List<Employee> emps; // setter and getter }
/** * oracle分页: * 借助rownum:行号;子查询; * 存储过程包装分页逻辑 * @throws IOException */ @Test public void testProcedure() throws IOException{ SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession openSession = sqlSessionFactory.openSession(); try{ EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); OraclePage page = new OraclePage(); page.setStart(1); page.setEnd(5); mapper.getPageByProcedure(page); System.out.println("总记录数:"+page.getCount()); System.out.println("查出的数据:"+page.getEmps().size()); System.out.println("查出的数据:"+page.getEmps()); }finally{ openSession.close(); } }