首页 > 编程语言 > 详细

(10).spring与mybatis的集成 业务层的必须性

时间:2020-06-14 22:43:33      阅读:62      评论:0      收藏:0      [点我收藏+]

spring与mybatis的集成:

步骤:

1.jar包。mybatis-spring jar包。加入jar包。创建mybatis与spring的连接能力。

2.创建spring配置文件main.xml

spring是有多个配置文件的,分类:1.按功能分组,2.按模块分+公共的

1.执行:在src下创建springxml类型的main.xml

当mybatis集成spring之后,我们之前写的mybatisUtils类就可以被代替了。

由于我们需要工厂创建机制:SqlSession->依赖于SqlSessionFactory->1.数据连接,2.映射文件和接口

2.此时映射文件和接口是现成的,只需加载即可。数据库连接可通过commons-dbcp-1.4.jar进行解决,提供了一个开源的DataSource(记不住可以直接看jar包)

开始配置:

配置main.xml,连接数据库。

<!--数据源:Spring管理的数据源、web容器管理的数据源-->
<bean class="org.apache.commons.dbcp.BasicDataSource" id="dataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/news?characterEncoding=utf8&amp;useUnicode=true&amp;serverTimezone=Asia/Shanghai"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
<property name="initialSize" value="2"/><!---连接数,初始的时候有几个连接池,连接数-->
<property name="maxActive" value="10"/><!---最大连接数-->
<property name="minIdle" value="2"/><!---最小空闲数, 空闲连接,-->
</bean>

 

之后进行SqlSessionFactory的配置(将mybatis中的mybatisUtil交给spring进行工作)(本次的作用为:1.连接数据库,2.扫描映射文件)

 <!--创建工厂机制SqlSessionFactory-->
    <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sessionFactory">
        <property name="dataSource" ref="dataSource"/>
        <property name="mapperLocations" value="classpath:com/dao/*.xml"/>
    </bean>

 

  spring自动生成Mapper实现类的bean,是dao层里xml文件里类的首字母小写。

<!--Spring自动生成Mapper实现类的bean,相当于获取Mapper类的配置的bean-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.dao"/><!--扫描包,即扫描Dao包-->
<property name="sqlSessionFactoryBeanName" value="sessionFactory"/>
</bean>

 

单元测试:表示可以获取类的bean:

package com.dao;

import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class NewsMapperTest {
    static ApplicationContext ctx = null;
    @BeforeClass
    public static void load(){
        ctx = new ClassPathXmlApplicationContext("main.xml");
    }
    @Test
    public void mapper(){
        NewsMapper newsMapper = (NewsMapper)ctx.getBean("newsMapper");
        Assert.assertNotNull(newsMapper);
    }
}

为什么需要业务层:

1、共同语言,程序员<=客户语言、词汇、业务=>客户
2、使用多个Mapper对象操作数据库
3、事务、日志、异常、安全都位于业务层
NewsMapper->NewsService->NewsController->页面

 

业务类使用接口,目的是解决spring中代理模式的问题。

eg:接口

package com.service;

import com.bean.News;

import java.util.List;
import java.util.Map;

/**
 * 1、共同语言,程序员<=客户语言、词汇、业务=>客户
 * 2、使用多个Mapper对象操作数据库
 * 3、事务、日志、异常、安全都位于业务层
 * NewsMapper->NewsService->NewsController->页面
 */
public interface NewsService {
    void publish(News news);
    void edit(News news);
    void approve(News news);
    News get(int id);
    News get(Map<String, Object> params);
    List<News> list(Map<String, Object> params);
}

实现:

package com.service.impl;

import com.bean.News;
import com.dao.NewsMapper;
import com.dao.UsersMapper;
import com.service.NewsService;
import java.util.List;
import java.util.Map;

public class NewsServiceImpl implements NewsService {

    private NewsMapper newsMapper;

    @Override
    public void publish(News news) {
        news.setPubtime(new java.util.Date());
        news.setState(1);    // 新建新闻
        news.setIsElite(0);  // 非精华帖
        newsMapper.add(news);
    }

    @Override
    public void edit(News news) {
        newsMapper.update(news);
    }

    @Override
    public void approve(News news) {

    }

    @Override
    public News get(int id) {
        return newsMapper.findNewsWithReplys(id);
    }

    @Override
    public News get(Map<String, Object> params) {
        return newsMapper.findNewsByParams(params);
    }

    @Override
    public List<News> list(Map<String, Object> params) {
        return newsMapper.find(params);
    }

    public NewsMapper getNewsMapper() {
        return newsMapper;
    }

    public void setNewsMapper(NewsMapper newsMapper) {
        this.newsMapper = newsMapper;
    }
}

在添加用户的业务层中控制事务:

问题:在我们写了add方法操作后,并没有进行commit操作。我们执行add方法(方法带有事务)操作仍然会成功添加,此时并不是我们想要的,于是我们需要管理事务。

方法:采用AOP的方式实现。

问题:在业务层,在两个相近的两个数据库操作,并不是只打开一次数据库,而是两次。

配置步骤:

  1. 导入tx和aop命名空间。
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd ">

     

  2. 定义事务管理器Bean,并为其注入数据源Bean。
    <!--导入事务管理器-->
        <bean id="transactionManager"
              class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"/>
        </bean>

     

  3. 通过<tx:advice>配置事务增强,绑定事务管理器并针对不同方法定义事务规则。
    <!--配置事务的规则-->
        <tx:advice id="transAdvice" transaction-manager="transactionManager">
            <tx:attributes>
                <tx:method name="*" read-only="true"/>           <!--拒绝所有,所有只读-->
                <tx:method name="publish" propagation="REQUIRED"/>
                <tx:method name="edit" propagation="REQUIRED"/>
            </tx:attributes>
        </tx:advice>

    配置事务的规则:那些方法上如何运用事务:1.白名单机制:拒绝所有,允许个别。2.黑名单机制:允许所有,拒绝个别。属性:propagation(传播属性):requried表示必须要。support(表示支持事务,常需要两个事务配合)。isolation(隔离性):read_committed(绝大多数需要的)

  4. 配置切面,将事务增强与方法切入点组合。 
    <!--编织-->
        <aop:config>
            <aop:pointcut id="servicePointcut"
                          expression="execution(* com.service..*.*(..))"/>
            <aop:advisor advice-ref="transAdvice" pointcut-ref="servicePointcut"/>
        </aop:config>

    在com.service子包下的类进行事务增强,增强的是transAdvice.

  5. 结果:通过以上4步的“白名单”操作会致使只有publish与edit两个方法可以进行事务的操作。其他的方法不允许。并且相近的两个数据库操作会只打开一次数据库,提交一次事务。

 问题:白名单控制在业务层,那么如果有人直接访问Dao层如何处理?

 问题:在dao层依旧可能会出现挨着的两个事务会出现打开两次数据库的问题。

即直接通过newsMapper进行数据库的操作。

解决方法:类似于业务层:

第一步与第二步与上一个相同:

第三步:通过<tx:advice>配置事务增强,绑定事务管理器并针对不同方法定义事务规则。

<tx:advice id="daoAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="*" read-only="true"/>
        </tx:attributes>
</tx:advice>

第四步:编织,使切入点与事务规则进行配置。

<!--编织-->
    <aop:config>
        <aop:pointcut id="servicePointcut"
                      expression="execution(* com.service..*.*(..))"/>
        <aop:pointcut id="daoPointvut" expression="execution(* com.dao..*.*(..))"/>
        <aop:advisor advice-ref="transAdvice" pointcut-ref="servicePointcut"/>
        <aop:advisor advice-ref="daoAdvice" pointcut-ref="daoPointvut"/>
    </aop:config>

结果:此时dao层则会不再能进行添加等数据库操作。

总结:目前以上操作:在业务层可以进行数据库操作业务处理,而无法直接通过dao层进行处理。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
">
    <!--数据源:Spring管理的数据源、web容器管理的数据源-->
    <bean class="org.apache.commons.dbcp.BasicDataSource" id="dataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://127.0.0.1:3306/news?characterEncoding=utf8&amp;useUnicode=true&amp;serverTimezone=Asia/Shanghai"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
        <property name="initialSize" value="2"/><!---连接数,初始的时候有几个连接池,连接数-->
        <property name="maxActive" value="10"/><!---最大连接数-->
        <property name="minIdle" value="2"/><!---最小空闲数, 空闲连接,-->
    </bean>
    <!--创建工厂机制SqlSessionFactory-->
    <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sessionFactory">
        <property name="dataSource" ref="dataSource"/>
        <property name="mapperLocations" value="classpath:com/dao/*.xml"/>
    </bean>
    <!--Spring自动生成Mapper实现类的bean,相当于获取Mapper类的配置的bean-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.dao"/><!--扫描包,即扫描Dao包-->
        <property name="sqlSessionFactoryBeanName" value="sessionFactory"/>
    </bean>
    <bean class="com.service.impl.NewsServiceImpl" id="newsService">
        <property name="newsMapper" ref="newsMapper"/>
    </bean>
    <!--导入事务管理器-->
    <bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--配置事务的规则:那些方法上如何运用事务-->
    <tx:advice id="transAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="*" read-only="true"/>
            <tx:method name="publish" propagation="REQUIRED"/>
            <tx:method name="edit" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
    <tx:advice id="daoAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="*" read-only="true"/>
        </tx:attributes>
    </tx:advice>
    <!--编织-->
    <aop:config>
        <aop:pointcut id="servicePointcut"
                      expression="execution(* com.service..*.*(..))"/>
        <aop:pointcut id="daoPointvut" expression="execution(* com.dao..*.*(..))"/>
        <aop:advisor advice-ref="transAdvice" pointcut-ref="servicePointcut"/>
        <aop:advisor advice-ref="daoAdvice" pointcut-ref="daoPointvut"/>
    </aop:config>
    
</beans>

对于上面关于dao层直接处理数据库的操作问题,不建议这样,已注解掉。关于这个问题,是可以通过管理手段来解决这个问题。

 

(10).spring与mybatis的集成 业务层的必须性

原文:https://www.cnblogs.com/zxdup/p/13122261.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!