Mybatis开发流程
一.简单描述
MyBatis最关键的组成部分是SqlSessionFactory,我们可以从中获取SqlSession, 并执行映射的SQL语句。SqlSessionFactory对象可以通过基于XML的配置信息或者JavaAPI创建.而mybatis-config.xml配置文件就是SqlSessionFactory生成的基础
0.需要引入mybatis.jar包
可以在我的网盘上下载:https://pan.baidu.com/s/1r-PZPSfru2Pf53u_lNIFTg
提取码:d891
网上的下载地址:https://github.com/mybatis/mybatis-3/releases
准备相应的dtd文件
我的网盘:https://pan.baidu.com/s/1PpatVfp9kcNsQxUbYFdZJQ
提取码:1kp8
网上的下载地址:http://www.mybatis.org/mybatis-3/
1.准备全局的配置文件 mybatis_config.xml,一般放在src下,里面有数据库连接的四要素
(1).environments是配置mybatis当前工作的数据库环境的地方
<environments default="db1">
<environment id="db1">
四要素
事务管理方式
</environment>
<environment id="db2">
四要素
事务管理方式
</environment>
...
</environments>
MyBatis支持配置多个dataSource环境,可以将应用部署到不同的环境上,可以通过将默认environments的【default属性】设置成想要的environment的id值
(2).transcationManager事务管理器,取值JDBC或MANAGED
JDBC表示手动控制
MANAGED被服务器管理
(3).dataSource元素,dataSource表示的是【数据源】:至少会包括该连接数据库的各种信息
a.
<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>
b.dataSource的类型type属性可以配置成其内置类型之一,如【UNPOOLED,POOLED,JNDI(web使用)】
c.如果将类型设置成UNPOOLED,MyBatis会为每一个数据库操作创建一个新的连接,使用完了并关闭它,该方式适用于只有小规模数量并发用户的简单应用程序上。
d.如果将属性设置成POOLED,MyBatis会【创建】一个【数据库连接池】,连接池中的一个连接将会被用作数据库操作。一旦数据库操作完成,MyBatis会将此连接返回给连接池。在开发或测试环境中,经常使用此种方式
e.数据库连接池:弄个池子,预先创建出来多个数据库连接对象,用户使用时,直接从池子里面拿一个出来,使用完成后不要关闭,而是将连接对象放回池子
(4).transactionManager元素 :事务管理器
MyBatis支持两种类型的事务管理器:JDBC 和 MANAGED.
(5).properties元素:作用是 定义变量。
(6).typeAliases元素:类型别名,放在properties后面
(7).typeHandlers元素: 类型处理器
(8).settings元素: 全局参数设置
(9).mappers元素: SQL映射
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>
<!-- properties标签必须 是第一个子标签,定义变量,定义完成后,可以后面的标签中使用-->
<!-- 注意:resource引入的配置文件 优先级更高 -->
<properties resource="driver.properties">
<property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
<property name="username" value="chb"/>
<property name="pw" value="briup"/>
</properties>
<!-- 一般使用默认配置即可 -->
<!--<settings>
<setting name="logPrefix" value="XN: "/>
</settings> -->
<typeAliases>
<!-- <typeAlias type="com.briup.pojo.Student" alias="Student" /> -->
<!-- 将该包 下 所有类都设置别名为 类名 -->
<package name="com.briup.pojo"/>
</typeAliases>
<!-- 设置自定义类型处理器 ps.setXxx() -->
<typeHandlers>
<typeHandler handler="com.briup.typehandlers.PhoneTypeHandler"/>
</typeHandlers>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:XE" />
<property name="username" value="${username}" />
<property name="password" value="${pw}" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/briup/mappers/DynamicSqlMapper.xml"/>
</mappers>
</configuration>
2.自定义类型处理器
PhoneTypeHandler.java
package com.briup.typehandlers;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import com.briup.pojo.PhoneNumber;
public class PhoneTypeHandler extends BaseTypeHandler<PhoneNumber> {
//遇到PhoneNumber参数的时候应该如何在ps中设置值
@Override
public void setNonNullParameter(PreparedStatement ps, int index, PhoneNumber phone, JdbcType jdbcType)
throws SQLException {
ps.setString(index, phone.getAsString());
}
//查询中遇到PhoneNumber类型的应该如何封装(使用列名封装)
@Override
public PhoneNumber getNullableResult(ResultSet rs, String columnName) throws SQLException {
String str = rs.getString(columnName);
return new PhoneNumber(str);
}
//查询中遇到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));
}
}
PhoneNumber类如下:
package com.briup.pojo;
public class PhoneNumber {
private String countryCode;
private String stateCode;
private String number;
public PhoneNumber(){}
//"110-119-120"
public PhoneNumber(String str) {
if(str != null) {
String[] arr = str.split("-");
this.countryCode = arr[0];
this.stateCode = arr[1];
this.number = arr[2];
}
}
public PhoneNumber(String countryCode, String stateCode, String number) {
this.countryCode = countryCode;
this.stateCode = stateCode;
this.number = number;
}
//由“电话号码对象” 获取其对应的字符串
public String getAsString() {
return countryCode + "-" + stateCode + "-" + number;
}
public String getCountryCode() {
return countryCode;
}
public void setCountryCode(String countryCode) {
this.countryCode = countryCode;
}
public String getStateCode() {
return stateCode;
}
public void setStateCode(String stateCode) {
this.stateCode = stateCode;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
@Override
public String toString() {
return "PhoneNumber [countryCode=" + countryCode + ", stateCode=" + stateCode + ", number=" + number + "]";
}
}
3.准备具体的映射文件DynamicSqlMapper.xml,一般的命名方式是xxxMapper.xml,里面放sql语句
DynamicSqlMapper.xml文件内容如下
<?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">
<!-- com.briup.mappers.DynamicSqlMapper是我们定义接口的全限定名字 这样就可以使用接口调用映射的SQL语句了 这个名字一定要和接口对应上-->
<mapper namespace="com.briup.mappers.DynamicSqlMapper">
<resultMap type="Course" id="CourseResult">
<id column="course_id" property="courseId" />
<result column="name" property="name" />
<result column="description" property="description" />
<result column="start_date" property="startDate" />
<result column="end_date" property="endDate" />
</resultMap>
<!--这里编写sql语句--><!-- 按照if条件 动态查找信息 -->
<select id="searchCourses" parameterType="map" resultMap="CourseResult">
SELECT * FROM COURSES
WHERE TUTOR_ID= #{tutorId}
<if test="courseName != null">
AND NAME LIKE #{courseName}
</if>
<if test="startDate != null">
AND START_DATE >= #{startDate}
</if>
<if test="endDate != null">
AND END_DATE <![CDATA[ <= ]]> #{endDate}
</if>
</select>
</mapper>
4.准备映射接口DynamicSqlMapper.java,里面放具体的抽象方法,【与sql语句所在的标签对应】,一般命名方式xxxMapper
DynamicSqlMapper.java文件内容如下
package com.briup.mappers;
import java.util.List;
import java.util.Map;
import com.briup.pojo.Course;
public interface DynamicSqlMapper {
//方法名与标签中id属性值对应
public List<Course> searchCourses(Map<String, Object> map);
}
5.设置sql工厂对象
package com.briup.utils;
import java.io.IOException;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class MyBatisSqlSessionFactory {
private static SqlSessionFactory sqlSessionFactory;
public static SqlSessionFactory getSqlSessionFactory(){
if(sqlSessionFactory == null){
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream("mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e.getCause());
}
}
return sqlSessionFactory;
}
public static SqlSession openSession() {
return openSession(false);
}
public static SqlSession openSession(boolean autoCommit) {
return getSqlSessionFactory().openSession(autoCommit);
}
}
6.准备测试代码
@Test
public void test_searchCourses_if(){
SqlSession session = null;
try {
//获取session对象
session = MyBatisSqlSessionFactory.openSession();
//获取接口的实现类对象
DynamicSqlMapper mapper = session.getMapper(DynamicSqlMapper.class);
Map<String,Object> map = new HashMap<String,Object>();
map.put("tutorId", 1);
map.put("courseName", "%Java%");
//接口实现类对象调用方法,自动执行sql语句
List<Course> list = mapper.searchCourses(map);
for(Course c:list){
System.out.println(c);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
if(session!=null)session.close();
}
}