目录
1.持久层整合
1.1Spring框架为什么要与持久层技术进行整合
1.Spring框架为什么要与持久层技术进行整合
1.JavaEE开发需要持久层进行数据库的访问操作------>需要
2.JDBC,Hibernate,Mybatis进行持久层开发过程中存在大量的代码冗余------>但是有冗余
3.Spring基于模版设计模式对于上述的持久层技术进行了封装------>我要改进,整合
2.Spring可以与哪些持久层技术进行整合
1. JDBC
|- JDBCTemplate
2. Hibernate (JPA)
|- HibernateTemplate
3. MyBatis
|- SqlSessionFactoryBean MapperScannerConfigure
1.2.MyBatis开发步骤回顾
MyBatis开发步骤回顾
1. 实体
2. 实体别名
3. 表
4. 创建DAO接口
5. 实现Mapper文件
6. 注册Mapper文件
7. MybatisAPI调用
-
1.添加pom坐标
<!--添加mysql驱动--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency> <!--mybatis--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.5</version> </dependency>
-
2.2个配置文件:
1.映射文件:xxxMapper.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"> <mapper> </mapper>
2.Mybatis配置文件:mybatis-config1.xml。
注意:我这里起名mybatis-config1.xml,是因为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> <typeAliases> </typeAliases> <environments default="mysql"> <environment id="mysql"> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <property name="dirver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/test_db?useSSL=false"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <mappers> </mappers> </configuration>
-
3.实体类
public class User implements Serializable { private Integer id; private String name; private String password; public User() { } public User(Integer id, String name, String password) { this.id = id; this.name = name; this.password = password; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
-
4.设置实体别名:之后在映射文件xxxMapper.xml中,就不用在写全限定类名了。
-
5.MySQL中创建user表:
-
6.定义DAO接口
public interface UserDao { void save(User user); }
-
7.创建对应的Dao的Mapper:UserMapper.xml
注意这里的parameterType="user"
中的user,就是在mybatis-config1中配置的别名:<typeAlias type="com.txl.example.mybatis.User" alias="user"/>
<?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.txl.example.mybatis.UserDao"> <insert id="save" parameterType="user"> insert into user(name, password) values (#{name}, #{password}) </insert> </mapper>
-
8.在mybatis-config1注册刚才写的Mapper
注意:这个Mapper直接放在了resources根下面
-
9.测试:获得对应Dao接口的实现类
UserDao userDao = sqlSession.getMapper(UserDao.class);
public class TestMybatis { public static void main(String[] args) throws IOException { InputStream inputStream = Resources.getResourceAsStream("mybatis-config1.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession(); UserDao userDao = sqlSession.getMapper(UserDao.class); User user = new User(); user.setName("ttxxll"); user.setPassword("123456"); userDao.save(user); sqlSession.commit(); } }
1.3.MyBatis开发过程中存在的问题
1.配置繁琐:配置很多的实体别名,每个Mapper文件都还要注册
2.代码冗余:
- 创建SqlSession的代码是固定的:但是每次获取SqlSession 时都要写一遍。
InputStream inputStream = Resources.getResourceAsStream("mybatis-config1.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession();
2.Spring与MyBatis整合
思路:主要是对这4行冗余的代码进行封装
2.1SqlSessionFactoryBean
封装获得SqlSessionFactory
1.Spring整合Mybatis后,就不用通过这两行代码获取SqlSessionFactory
。
InputStream inputStream = Resources.getResourceAsStream("mybatis-config1.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
通过一个Spring提供的类SqlSessionFactoryBean
,获得这个对象。
2.分析一下:mybatis-config.xml主要帮我做了哪些事:
3.所以即使通过Spring提供的类SqlSessionFactoryBean
,获得SqlSessionFactory
对象。还是需要数据源,别名配置,Mapper注册。那么SqlSessionFactoryBean
是怎么获得这些信息呢?
4.向SqlSessionFactoryBean
对象注册对应的成员变量:那么就可以省略mybatis-config.xml
配置文件了。
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="typeAliasesPackage" value="com.baizhiedu.entity"> </property>
<property name="mapperLocations">
<list>
<value>classpath:com.baizhiedu.mapper/*Mapper.xml</value>
</list>
</property>
</bean>
5.减少了配置:
<property name="typeAliasesPackage" value="com.baizhiedu.entity">
为整个包配置别名,减少了别名的配置。- 通配注册方式Mapepr:注册以Mapper结尾的文件,减少了注册Mapper的配置
<property name="mapperLocations"> <list> <value>classpath:com.baizhiedu.mapper/*Mapper.xml</value> </list> </property>
2.2获得SqlSession和对应Dao接口的实现类
1.拿到SqlSessionFactoryBean创建的SqlSessionFactory
2.提供Dao接口的.class
3.Spring提供了一个类MapperScannerConfigure来帮我们做到上述过程。
MapperScannerConfigure
封装好了上面两句代码。
<!--创建DAO对象 MapperScannerConfigure-->
<bean id="scanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBean"></property>
<!--设置Dao接口所在包:并且创建Dao接口的实现类-->
<property name="basePackage" value="com.baizhiedu.dao"></property>
</bean>
-
注意:MapperScannerConfigure可以帮我们创建Dao对象,它的id值是接口手单词字母小写。
-
注意:
为什么在注入sqlSessionFactoryBeanName属性时,要用value注入sqlSessionFactoryBean而不是ref注入sqlSessionFactoryBean?
1.首先MapperScannerConfigure类中的sqlSessionFactoryBeanName这个属性本身就是String类型的,所以用value注入。
-
按理说这个属性应该是SqlSessionFactoryBeanName类型的属性,为什么这里定义成String的呢?
在mybatis-spring 1.1.0以前,是通过将SqlSessionFactory对象注入到sqlSessionFactory,这样做可能会有一个问题,就是在初始化MyBatis时,jdbc.properties文件还没被加载进来,dataSource的属性值没有被替换,就开始构造sqlSessionFactory类,属性值就会加载失败。在1.1.0以后,MapperScannerConfigure提供了String类型的sqlSessionFactoryBeanName,这样将bean name注入到sqlSessionFactoryBeanName,这样就会等到spring初始化完成后,再构建sqlSessionFactory。因为value 属性需要一个正确并且存在的值。如果配置文件出错,或者没被加载,整个dataSource 就不存在,那么sqlSessionFactory 也是错误的,不存在的值, value值就不存在,不会在这个地方抛出异常;但是使用ref 属性,就会出现,不管这个引入的值对不对,都会被使用。但实际会因为这个值不存在,导致异常。
2.3分析小结
2.4Spring整合Mybatis的开发步骤
1.配置文件相关的配置
#配置 是需要配置一次
<bean id="dataSource" class=""/>
<!--创建SqlSessionFactory-->
<bean id="ssfb" class="SqlSessionFactoryBean">
<property name="dataSource" ref=""/>
<property name="typeAliasesPackage">
指定 实体类所在的包 com.baizhiedu.entity User
Product
</property>
<property name="mapperLocations">
指定 配置文件(映射文件)的路径 还有通用配置
com.baizhiedu.mapper/*Mapper.xml
</property>
</bean>
<!--DAO接口的实现类
session ---> session.getMapper() --- xxxDAO实现类对象
XXXDAO ---> xXXDAO
-->
<bean id="scanner" class="MapperScannerConfigure">
<property name="sqlSessionFactoryBeanName" value="ssfb"/>
<property name="basePacakge">
指定 DAO接口放置的包 com.baizhiedu.dao
</property>
</bean>
2.编码步骤:只剩4步了
1. 实体
//2. 实体别名
3. 表
4. 创建DAO接口
5. 实现Mapper文件
//6. 注册Mapper文件
//7. MybatisAPI调用
2.5Spring整合Mybatis的编码
1.导入jar包:pom
<!--添加mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--jdbc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.14.RELEASE</version>
</dependency>
<!--Spring整合mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.2</version>
</dependency>
<!--druid连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.18</version>
</dependency>
2.Spring配置文件
<!--1.配置连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test_db?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!--2.配置创建SqlSessionFactory的SqlSessionFactoryBean-->
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="typeAliasesPackage" value="com.txl.example.mybatis.entity"/>
<property name="mapperLocations">
<list>
<value>classpath:mappers/*.xml</value>
</list>
</property>
</bean>
<!--3.MapperScannerConfigure创建Dao接口的实现对象-->
<bean id="scanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBean"/>
<property name="basePackage" value="com.txl.example.mybatis.dao"/>
</bean>
3.编码
1.实体
2.表
3.Dao接口
4.Mapper文件配置
- 注意:在编写Mapper文件配置,注意到我们在applicationContext配置了实体类的别名默认是类名。
4.测试
@org.junit.Test
public void test0(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/applicationContext.xml");
UserDao userDao = (UserDao)applicationContext.getBean("userDao");
User user = new User();
user.setName("txl");
user.setPassword("123");
userDao.save(user);
}
3.整合mybatis细节
1.原来在单纯的应用mybatis时,增删改操作要加上事务。
2.现在发现Spring的工厂给我创建的Dao对象,我们执行了save操作后,没有进行事务提交。
3.没有事务操作,这个是怎么能完整无误的插入到数据库中呢?
4.核心是连接对象:Connection,连接对象控制事务,控制了连接对象,就相当于控制了事务。
5.谁控制了连接对象呢?
- Spring没有控制连接对象
- 本质上控制连接对象的是:连接池
5.以前单纯运用mybatis进行开发的时候,Mybatis提供了一个连接池对象,进而创建连接对象。现在整合后,是Druid连接池创建连接对象。
6.两者的差别:
- Mybatis提供的连接池对象连接池在创建连接对象是会将:Connection.setAutoCommit(false)设置为false,意味着需要手工的控制事务 ,操作完成后,手工提交。
- 而Druid(C3P0也是的)连接池设置Connection.setAutoCommit(true) true且是默认值,保持自动控制事务,一条sql 自动提交 。
7.因为Spring与Mybatis整合时,引入了外部连接池对象,保持自动的事务提交这个机制(Connection.setAutoCommit(true)),不需要手工进行事务的操作,也能进行事务的提交 。
8.一个业务涉及多条sql时,我们想把这多条sql当作一个整体,一起成功一起失败
。后续Spring会通过事务控制来解决这个问题。