Spring事务(登录注销的实现)

1、登录/注销
1.1、登录记录用户状态
@RequestMapping("/dologin")
	public String doLogin(Model model,String username,String userpass,HttpSession session) {
		UserInfo user = service.selectUserInfoByUserName(username, userpass);
		if (user!=null) {
			if (userpass.equals(user.getUserpass())) {
				//保存用户登录状态
				session.setAttribute("user", user);
				return "redirect:/goods/findall/1";
			} else {
				model.addAttribute("userpassErr", "密码错误");
				return "login/login";
			}
		}
		model.addAttribute("userErr", "用户名或密码错误");
		return "login/login";
	}
1.2、注销用户状态
@RequestMapping("/logout")
public String logout(HttpSession session) {
	//退出(session失效)
    //基于登录状态下放入session中所有的属性,如用户信息(状态),购物车等
	session.invalidate();
	//session移除某一个属性
	//session.removeAttribute("user");
	return "login/login";
}
2、框架中的分页
  • 一般步骤:

  • pom.xml配置文件中引入分页jar包

    <dependency>
    	<groupId>com.github.pagehelper</groupId>
    	<artifactId>pagehelper</artifactId>
    	<version>5.1.11</version>
    </dependency>
    
  • SqlMapConfig.xml配置文件中配置分页参数合理化

    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
        <!-- 分页参数合理化,pageNum<=0 时会查询第一页, pageNum>pages(超过总数时),会查询最后一页 -->
    	  <property name="reasonable" value="true"/>
    	</plugin>
    </plugins>
    
  • 在处理器Controller查询全部信息应用分页

    • 用restful注入第几页{pageNum}

      @PathVariable("pageNum")Integer pageNum

  • @RequestMapping("/findall/{pageNum}")
    	public String findAll(Model model,@PathVariable("pageNum")Integer pageNum) {
    		// 用业务类调用mapper
    		//1、设置查询页码和一页显示几行记录
    		PageHelper.startPage(pageNum, 2);
    		//2、紧跟着第一个查询
    		List<Goods> list = service.findAll();
    		//3、 页面显示的本页数据封装到pageInfo中,将分页导航按钮的数量封装PageInfo中
    		PageInfo<Goods> pageInfo = new PageInfo<Goods>(list,3);
    		//4: 返回页面pageInfo回显到页面
    		model.addAttribute("pageInfo", pageInfo);
    		return "goods/findall";
    	}
    
3、事务控制
  • 第一步:导入jar包

    //导入Spring-jdbc的jar包
    <dependency>
    	<groupId>org.springframework</groupId>
    	<artifactId>spring-jdbc</artifactId>
    	<version>5.3.13</version>
    </dependency>
    
    //导入Spring-AOP的jar包
    <!-- Spring AOP -->
    <dependency>
    	<groupId>org.springframework</groupId>
    	<artifactId>spring-aop</artifactId>
    	<version>5.3.13</version>
    </dependency>
    <dependency>
    	<groupId>org.aspectj</groupId>
    	<artifactId>aspectjrt</artifactId>
    	<version>1.8.10</version>
    </dependency>
    <dependency>
    	<groupId>org.aspectj</groupId>
    	<artifactId>aspectjweaver</artifactId>
    	<version>1.8.10</version>
    </dependency>
    
  • 第二步:配置事务管理器

    <!-- 在springmvc.xml配置文件中,配置声明式事务-定义事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    	<property name="dataSource" ref="dataSource"></property>
    </bean>
    
    
  • 使用方式1:使用注解@Transactional管理事务

    • 第一步:启动事务注解扫描

      <!-- 在springmvc.xml配置文件中,配置声明式事务-启用事务注解扫描 -->
      <tx:annotation-driven transaction-manager="transactionManager"/>
      
    • 第二步:使用注解@Transactional管理事务

      • 将@Transactional注解标注在业务方法上,表示告诉Spring容器,该方法调用前要打开事务,方法调用结束后提交或回滚事务。
      • 将@Transactional注解标注在业务类上,表示告诉Spring容器,该类中的所有方法调用前要打开事务,方法调用结束后提交或回滚事务。
      • 如果方法内抛出运行时异常(RuntimeException),事务将回滚。
      • 方法内抛出编译时异常(Exception),事务将提交。
      @Autowired
      	OrderDetailMapper detailMapper = null;
      	//@Transactional
      	public int insert(Orders orders,List<OrderDetail> detaillist) {
      		//给订单表添加数据
      		int rows = orderMapper.insert(orders);
      		if(1==1)
      			throw new CustcomException("添加数据出错了");
      	    //订单明细明细添加数据
      		for (OrderDetail detail : detaillist) {
      			detail.setOrderid(orders.getId());
      			detailMapper.insert(detail);
      		}
      		return rows;
      	}
      
  • 使用方式2:基于xml配置管理事务

    • 第一步:定义事务切入点

      <!-- spring:定义事务切入点:确定在调用什么方法时启用声明式事务 -->
      <aop:config>  
          <aop:pointcut id="serviceMethod" expression="execution(* com.kaifamiao.service..*.*(..))"/>  
          <aop:advisor pointcut-ref="serviceMethod" advice-ref="txAdvice"/>  
      </aop:config>  
      
    • 第二步:定义事务的Advice

      <!-- spring:配置应用事务的advice,以明确哪些方法需要开启事务,哪些方法不需要开启事务 -->
      <tx:advice id="txAdvice" transaction-manager="transactionManager">  
          <tx:attributes>  
              <tx:method name="save*" propagation="REQUIRED" isolation="READ_COMMITTED"/>
              <tx:method name="insert*" propagation="REQUIRED" isolation="READ_COMMITTED"/>
              <tx:method name="add*" propagation="REQUIRED" isolation="READ_COMMITTED"/>
              <tx:method name="create*" propagation="REQUIRED" isolation="READ_COMMITTED"/>
              <tx:method name="update*" propagation="REQUIRED" isolation="READ_COMMITTED"/> 
              <tx:method name="delete*" propagation="REQUIRED" isolation="READ_COMMITTED"/> 
              
              <tx:method name="find*" propagation="SUPPORTS" read-only="true" />
              <tx:method name="select*" propagation="SUPPORTS" read-only="true" />
              <tx:method name="get*" propagation="SUPPORTS" read-only="true" />
              
              <tx:method name="*" propagation="REQUIRED" isolation="READ_COMMITTED" read-only="true"/>  
          </tx:attributes>  
      </tx:advice>
      
4、Spring事务中哪几种事务传播行为?
  • Propagation用于设置事务的传播行为,事务的传播行为是指从一个开启事务的方法调用另外一个方法时,是否将事务传播给被调用方法。Spring中七种事务传播行为

    事务传播行为类型说明
    REQUIRED:(必须)如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
    SUPPORTS:(支持)支持当前事务,如果当前没有事务,就以非事务方式执行。
    MANDATORY:(强制)使用当前的事务,如果当前没有事务,就抛出异常。
    REQUIRES_NEW:(必须开启新事务)新建事务,如果当前存在事务,把当前事务挂起。
    NOT_SUPPORTED:(不支持)以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
    NEVER: (从不)以非事务方式执行,如果当前存在事务,则抛出异常。
    NESTED:(内部)如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
5、Spring事务中的隔离级别有哪几种?
  • DEFAULT 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.
  • 未提交读(read_uncommited) :脏读,不可重复读,虚读都有可能发生
  • 已提交读 (read_commited):避免脏读。但是不可重复读和虚读有可能发生
  • 可重复读(repeatable_read) :避免脏读和不可重复读.但是虚读有可能发生.
  • 串行化的(serializable) :避免以上所有读问题.
6、如果多个事务并发操作同一个资源,可能会发生的问题
  • 脏读:一个事务读取到另外一个事务未提交的更新数据
  • 不可重复读:在同一个事务中,多次读取同一个数据,返回的结果不同。意思是说后面的读取可以读到另外一个事务已经提交的更新数据。
  • 可重复读:在同一个事务中多次读取数据时,能保证每次所读取的数据都是一样的,意思是说后面读取不能读到另外一个事务提交的更新数据。
  • 幻想读:一个事务读取到另外一个事务已经提交的insert或delete数据。例如当对某行执行插入或删除操作,而该行属于某个事务正在读取的行的范围时,会发生幻像读问题。事务第一次读的行范围显示出其中一行已不复存在于第二次读或后续读中,因为该行已被其它事务删除。同样,由于其它事务的插入操作,事务的第二次或后续读显示有一行已不存在于原始读中。
7、数据库系统提供了5种事务隔离级别

​ default 默认的隔离级别

  • Read Uncommited:未提交读隔离级别(会出现脏读、不可重复读、幻想读)

  • Read Commited:已提交读隔离级别(不会出现脏读,会出现不可重复读、幻想读)

  • Repeatable Read: 可重复读(不会出现脏读、不可重复读,会出现幻想读)

  • Serializable:串行化(不会出现脏读、不可重复读、幻想读)

    在xml中没有提示时,将本地的文件,导入,在xml中就会有提示。

image-20211203231415816

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值