Mybatis基本运行流程
总结JDBC的问题:
1、数据库连接创建、释放频繁造成系统资源浪费,从而影响系统性能。如果使用数据库连接池可解决此问题。
2、Sql语句在代码中硬编码,造成代码不易维护,实际应用中sql变化的可能较大,sql变动需要改变java代码。
3、使用preparedStatement向占有位符号传参数存在硬编码,因为sql语句的where条件不一定,可能多也可能少,修改sql还要修改代码,系统不易维护。
4、对结果集解析存在硬编码(查询列名),sql变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成pojo对象解析比较方便。
1.Mybatis介绍
SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装。MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO映射成数据库中的记录
自动映射生成最终执行的sql语句,并将sql语句执行结果自动映射成java对象,返回给业务层(service)应用。
Mybatis的整体架构:

2.Mybatis的生命周期
(1)SqlSessionFactoryBuilder:作用就是创建一个构建器,一旦创建了SqlSessionFactory,它的任务就算完成了,可以回收。
(2)SqlSessionFactory:作用是创建SqlSession,而SqlSession相当于JDBC的一个Connection对象,每次应用程序需要访问数据库,我们就要通过SqlSessionFactory创建一个SqlSession,所以SqlSessionFactory在整Mybatis整个生命周期中(每个数据库对应一个SqlSessionFactory,是单例产生的)。
(3)SqlSession:生命周期是存在于请求数据库处理事务的过程中,是一个线程不安全的对象(在多线程的情况下,需要特别注意),即存活于一个应用的请求和申请,可以执行多条SQL保证事务的一致性。
(4)Mapper:是一个接口,它的作用是发送SQL(其中的方法相当于JDBC中的Statement),返回我们需要的结果,或者发送SQL修改数据库表,所以它存活于一个SqlSession内,是一个方法级别的东西。当SqlSession销毁的时候,Mapper也会销毁。
为什么SqlSessionFactory是单例的:
3.Mybatis的配置
3.1单独使用Mybatis的配置

1.按照上面的步骤首先定义一个User类
User.java
public class User { private Integer id; private String username; private Integer[] ids; private List<Integer> idlist; public Integer[] getIds() { return ids; } public void setIds(Integer[] ids) { this.ids = ids; } public List<Integer> getIdlist() { return idlist; } public void setIdlist(List<Integer> idlist) { this.idlist = idlist; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @Override public String toString() { return "User [id=" + id + ", username=" + username + "]"; } } 2.接着定义一个Mapper接口:定义了一些方法来操作数据库,方法中具体sql语句的实现在相应的xml文件中。
UserMapper.interface
public interface UserMapper { /* * 遵循四个原则: * 1.方法名和UseMapper.xml中<mapper>标签中sql标签的id属性值相同 * 2.方法的返回值和<mapper>标签中标签的resultType属性值相同 * 3.方法的参数类型和<mapper>标签中标签的parameterType属性值相同 * 4.xml中<mapper>标签的namespace属性值和此接口的全类名相同 */ User findUserById(Integer id); } 3.接着定义Mapper的映射文件UserMapper.xml,此文件的作用就是映射方法实现具体的SQL语句。
<mapper namespace="Mapper.UserMapper"> <!-- 设置一个sql片段 可以SQL语句中在引用--> <sql id="selector"> select * from user </sql> <select id(方法名)="findUserById" parameterType(方法的参数类型)="Integer" resultType(方法的返回类型)="pojo.User"> <include refid="selector"/> where id = #{id} </select> </mapper> 4.定义了UserMapper和UserMapper.xml之后那么程序如何才能寻找到呢,通过Mybatis的配置文件。
sqlMapConfig.xml
<configuration> <!-- 指定加载配置文件 --> <properties resource="jdbc.properties"/> <!-- 别名设置 --> <typeAliases> <package name="pojo"/> </typeAliases> <!-- 和Spring整合后这个标签就没用了 --> <environments default="development"> <environment id="development"> <!-- 使用jdbc事务管理 --> <transactionManager type="JDBC" /> <!-- 数据库连接池 --> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}" /> <property name="url" value="jdbc:mysql://localhost:3306/student" /> <property name="username" value="root" /> <property name="password" value="123456" /> </dataSource> </environment> </environments> <!-- 引入User的xml映射文件 我的UserMapper.java 和UserMapper.xml都在Mapper包下--> <mappers> <package name="Mapper"/> <!-- package这种方式需要接口名和xml文件名相同,直接导入包下所有配置文件 --> </mappers> </configuration> 5.配置好了配置文件创建一个demo实例来加载配置文件并创建sqlSessionFactory
UserDemo.java
public class UserDemo { @Test //通过id查询值 public void fun() throws IOException{ // 1.加载配置文件 InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml"); // 2.创建SqlSessionFactory SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(in); // 3.创建sqlSession SqlSession sqlSession=sqlSessionFactory.openSession(); // 4.sqlSeesion动态创建UserMapper实现类 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); // 5.实现类调用接口的方法,方法和映射文件一一对应 User user=userMapper.findUserById(1); System.out.println(user); } 3.2Mybatis整合Spring
applicationContext.xml
context:property-placeholder location="classpath:jdbc.properties"/> <!-- 将连接池注入容器 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <property name="maxActive" value="10" /> <property name="maxIdle" value="5" /> </bean> <!--配置工厂 --> <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <!-- 核心配置文件的位置 --> <property name="configLocation" value="classpath:sqlMapConfig.xml"/> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!-- 扫描包下的所有接口 --> <property name="basePackage" value="mapper"/> <!-- 这里会自动注入mapper接口 <bean name="userMapper" class="mapper.UserMapper"/> --> </bean> </beans> 这里的SqlSessionFactoryBean在Spring中最后创建的并不是Bean本身而是sqlSessionFactory
sqlMapConfig.xml文件只需设置一个别名(或者也不设置)
<configuration> <!-- 设置别名 --> <typeAliases> <!-- 2. 指定扫描包,会把包内所有的类都设置别名,别名的名称就是类名,大小写不敏感 --> <package name="pojo" /> </typeAliases> </configuration> UserDemo.java
@Test public void testMapper() throws Exception { ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); UserMapper mapper = ac.getBean(UserMapper.class); User user = mapper.selectUserById(1); System.out.println(user); } 这里的getBean会创建UserMapper的实现类