Spring整合Mybatis-----Aop事务
首先对于Spring整合Mybatis有两种方式那就是使用sql绝对定位以及使用Mapper代理来进行开发,本篇博文先来介绍第一种。
所谓的Sql绝对定位就是namespace+id得方式来进行定位;
首先对于Mybatis得介绍后面会有博文详细介绍,简单的说Mybatis得核心配置文件完成得就两个功能,一就是数据源得设置,而就是实体得注册(mapper层映射得注册);
接下来就开始创建项目:
1首先创建Maven项目,导入依赖
需要得包有Mybatis核心包,Spring,Mysql,log4j,dbcp
此外还需要generator.xml,log4j.properties得两个资源文件,前着是用自动生成pojo,mapper,Dao层得一个插件,后者主要是用来产生日志得;
建好了项目以后则通过这个插件来生成相应得类和文件,但是在此处我们不生产Dao及其接口,一步一步来,否则一下生成了我们也就不用干什么了,而且这样分开写便于理解,最主要得原因就是,底层完成得操做是增删改查,但是查是不需要事务的,所以这样我们可以提前对查进行测试;
不生成Dao接口及其实现类,只需要将这里的Dao接口生成的位置删除即可;
2.接下来我们就来创建Dao及其实现类
首先编写Dao接口,里面喜丧基本的增删改查,
注意的地方就是:方法名要和自动生成的Mapper文件的id一致,而其参数也要一致这样才能通过namespace+id来绝对定位到sql语句上,从而操作数据库;
再就是编写其实现类,但是这里为例方便操作,就不用以前的QuerruRunner了,这里Dao接口的实现类,再来继承一个类就是SqlsessionDaosupport,因为这个类会提供Sqlsession这个对象,但前提是我们要进行注入;
分析:小编通过源码得是SqlsessionDaosupport这个类得内部是:
this.sqlsession=newsqlsessionTemplate(sqlsessionFactory)
所以在注入得时候,我们应该注入得就是工厂,根据注入得工厂来得到sqlsesion对象。
那么sqlsession这个对象有什么用呢?
我们看一个添加用户得底层代码:
@Override
public void insert(User user) {
this.getSqlSession().insert("com.qf.mapper.UserMapper.insert",user);
}
很显然,代码得简洁性一目了然,对于用户得田间一句话搞定;
那么我们来解释一下这条语句:
1)首先因为我们注入了SqlsessionFactory,SqlsessionDaosupport这个类得内部对他进行了赋值,所以我们可以通过getSqlSession()来得到这个对象,在调用增删改查得方法;
2)com.qf.mapper.UserMapper.insert这就花就是我们所谓得nameSpace+id通过这条语句我们就可以来定位到,生成得mapper映射文件中得某个具体id方法,从而对数据库进行操作;
再接下来对删,改查的方法进行重写即可;
@Override public void deleteByPrimaryKey(Long id) { this.getSqlSession().delete("com.qf.mapper.UserMapper.insert.deleteByPrimaryKey",id); } @Override public void updateByPrimaryKey(User user) { this.getSqlSession().update("com.qf.mapper.UserMapper.insert.updateByPrimaryKey",user); } @Override public User selectByPrimaryKey(Long id) { User user=this.getSqlSession().selectOne("com.qf.mapper.UserMapper.insert.selectByPrimaryKey",id); return user; }
通过以上的操所我们以及完成了Dad层的创建
3 整合持久层
1) 首先我们要做的就是数据源的配置,
这个大家都比较熟悉了,再这里就不过多的赘述,就是url Driver username password 着写数据
2) 我们来创建sqlsession对象,
同时为其关联数据源依据前面提到的注入;
因为第层的增删改都是通过sqlsession来实现的所以得到的Sqlsession对象应该关联数据库;
下面就是具体的代码
创建Sqlsession对象
<bean id="SqlSessionFactoryBean"class="org.mybatis.spring.SqlSessionFactoryBean">
关联数据源
<property name="dataSource"value="datasource"></property>
注册实体相当于mybatis当中的注册映射
<propertyname="mapperLocations" >
<array>
<value>com/qf/mapper/UserMapper.xml</value>
</array>
</property>
</bean>
此处工厂用到的就是: SqlSessionFactoryBean
3)接下来我们就应该船舰UserDao对象
<bean name="UserDao"class="com.qf.Dao.UserDaoImpl">
在这里我们就对sqlsession对象进行了注入
<propertyname="sqlSessionFactory" value="SqlSessionFactoryBean"></property>
</bean>
Value就来自于之前创建的sqlsession对象的id
这样我们就完成了初次的整合,之后进行查找的测试即可;编写测试类
@Test public void testselectByPrimaryKey(){ ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml"); UserDao userDao=(UserDao) context.getBean("UserDao"); user user=userDao.selectByPrimaryKey(5L); System.out.println(user.getUsername()+"--"+user.getPassword()); context.close(); }
@Test这个声明是junit当中的测试注解,使用这个注解就可以对单个的方法进行测试而步骤使用main函数
以上就是对查找的测试。
4.Aop事务的整合
首先来编写服务层及其实现类
因为以后的数据都是从View层过来的,所以才这里我们需要额外船舰Dto层,来创建和玉面保持一致的实体类,因为有些数据用户是不会提交的需要我们自己设置,从而方便数据库的管理。
编写好服务层及其实现类之后,我们就对其进行配置以及Aop编程;
1)首先来说一下ServiceImpl实现类的写法:
因为服务层接受的是页面传过来的参数,所以可能会有Dto类型,这是就牵扯到一个数据搬移的问题,我们有两种方法来解决这个问题:
一个就是创建一个底层参数的对象,用get方法将Dto的值得到
再用set方法将这个值植入刚刚建好的对象中;
第二个就是使用BeanUtils.copypropertise(a,b)这个方法就是将a种的的数据复制到b中,但是它有一个使用的前提就是二者的类型是一致的;
废话不多说看一段代码就明白了:
@Override public void updataUser(UserDto dto) { User user=new User(); BeanUtils.copyProperties(dto,user); userDao.updateByPrimaryKey(user); }
2)就是我们应该再配置文件当中注入UserDao这样这儿才能使用userdao来调用底层的方法;
3)接下俩我们就来整合
ii)首先创建目标类对象,也就是服务层对象,代码如下:
<bean id="UserService"class="com.qf.service.UserServiceImpl">
再此处对UserServiceImpl该类当中的userDao属性来注入
<property name="userDao"value="UserDao"></property>
</bean>
III)船舰事务管理对象
因为事务是直接由Spring框架类提供的所以我们只需创建事务管理类的对象代码如下:
<bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<propertyname="dataSource" value="dataSource"></property>
</bean>
Class用到的就是DataSourceTransactionManager这个管理类。从而产生对象
再这个对象的内部 关联数据源因为事务也是可以操作数据库的比如说时间等。
Iv)定义事务通知切面,让事务应用到具体的方法,代码如下:
<tx:advice id="advice" transaction-manager="transactionManager">
让具体的方法加事务:add,del,update加事务,find不加
<tx:attributes>
<tx:method name="add*"propagation="REQUIRED"/>
<tx:method name="del*"propagation="REQUIRED"/>
<tx:method name="updata*"propagation="REQUIRED"/>
<tx:method name="find*"read-only="true"></tx:method>
</tx:attributes>
</tx:advice>
Find设置为只读;*好表示以前面的名称开头的方法,当然事务时应用到服务层的方法,所以指的就是服务层目标类的方法;
v)最后就是Aop编程
代码如下:
<aop:config>
创建切入点,用到的就是execution表达式即切入点表达式:
<aop:pointcut id="mypoint"expression="execution(* com.qf.service.*.*(..))"></aop:pointcut>
形成切面advice-ref关联公共类,pointcut-ref关联切点所以将通知和切入点关联就形成了切面
<aop:advisor advice-ref="advice"pointcut-ref="mypoint"></aop:advisor>
</aop:config>
vi)最后就是对服务层编写好的方法进程测试,代码如下:
@Test public void testInsert(){ ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService=(UserService) context.getBean("UserService"); UserDto user1=new UserDto(); user1.setUsername("傅筱"); user1.setPassword("123456"); userService.addUser(user1); } @Test public void test(){ ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService=(UserService) context.getBean("UserService"); UserDto user1=new UserDto(); user1.setId(15L); user1.setUsername("傅筱"); user1.setPassword("1111"); userService.updateUser(user1); }