SSM架构商城项目(八)

本周日正常上课

Spring事务

事务(Transaction)通常用于保证业务的完整性,通常,会有某些业务(需要执行的某个任务目标)需要执行多条SQL语句才可以完成,而在多条SQL语句的执行过程中,可能出现前序的执行成功,而后续的执行失败,就会导致数据不安全(数据没有根据我们设定的业务规则来发生变化),为了解决这个问题,就必须使用事务,从而保证多条SQL语句全部执行成功,或者全部执行失败!

可以认为:只要某个业务涉及2次或以上的增、删、改操作(例如2次修改,或1次增加与1次修改等),都必须使用事务来保障业务的完整性!而查询操作与事务无关,因为查询操作不会对数据进行修改,则不会影响到数据的安全性!

在Spring中,使用事务的流程:

  1. 涉及的增、删、改操作,必须能判断成功与否,并且,在失败时,抛出某种RuntimeException(可以是RuntimeException,也可以是它的子孙类异常);

  2. 业务对应的方法(调用了2次或更多次增、删、改的方法)必须添加@Transactional,该注解表示该方法的执行过程是有事务保护的,即执行之前开启了事务,如果全部成功则提交事务,中途出现任何错误会回滚事务。

  3. 开启@Transactional注解的驱动,即默认情况下,该注解是无效,因为无法识别!所以,在spring-dao.xml中添加配置(每次开发项目时只需要配置1次即可):




Spring的事务处理

Spring的事务处理大致是:

开启事务

try {
    调用带有@Transactional注解的方法

    提交事务
} catch (RuntimeException e) {
    回滚事务
}

Spring的事务管理是基于Spring AOP的!

@Transactional注解还可以添加在类的声明之前!但是,不推荐这样使用中!

提醒:复习事务的ACID、隔离、传播!

小结

在业务层,只要执行的是增、删、改操作,必须获取受影响的行数,并且,受影响的行数值不符合预期时,必须抛出某种RuntimeException

之所以开发过程中,自定义的的业务异常都需要继承自RuntimeException,一方面是为了满足Spring管理事务的要求,另一方面是为了通过Spring管理异常(参见BaseController)!

===============================================

6.2. 收货地址-查询列表

6.2.1. 收货地址-查询列表-持久层

在接口文件中添加新的抽象方法

List<Address> getList(Integer uid);

在配置文件中配置新的映射

SELECT * FROM t_address 
WHERE uid=?
ORDER BY is_default DESC, id DESC

6.2.2. 收货地址-查询列表-业务层

在业务层声明与持久层同名的方法,并实现。

完成后测试。

6.2.3. 收货地址-查询列表-控制器层

设计获取当前用户的收货地址列表的请求:

请求路径:/address/list.do
请求类型:GET
请求参数:无,HttpSession.uid
响应方式:ResponseResult<List<Address>>
是否拦截:是,登录拦截器,无须再次调整配置

然后,添加处理请求的方法:

@RequestMapping("/list.do")
@ResponseBody
public ResponseResult<List<Address>> getList(
    HttpSession session) {
    // 获取uid
    // 调用业务层方法获取列表
    // 创建返回值对象
    // 将列表封装到返回值对象中
    // 执行返回
}

6.2.4. 收货地址-查询列表-前端页面

(对原文件改动较多,请参考视频回放)

6.3. 收货地址-设置默认收货地址

6.3.1. 收货地址-设置默认收货地址-持久层

在接口中声明2个抽象方法:

Integer setNonDefault(Integer uid);

Integer setDefault(
    @Param("uid") Integer uid, 
    @Param("id") Integer id);

配置以上2个抽象方法的映射:

UPDATE t_address SET is_default=0 WHERE uid=?

UPDATE t_address SET is_default=1 WHERE id=? AND uid=?

6.3.2. 收货地址-设置默认收货地址-业务层

在业务层接口中添加:

/**
 * 设置某用户的某条收货地址为默认收货地址
 * @param uid 用户id
 * @param id 被设置为默认收货地址的数据的id
 */
void setDefaultAddress(Integer uid, Integer id);

在实现类中,先添加与持久相同的2个方法(不过,权限设置为private即可),然后,重写以上接口中的方法

6.3.3. 收货地址-设置默认收货地址-控制器层

6.3.4. 收货地址-设置默认收货地址-前端页面

6.4. 收货地址-删除

6.5. 收货地址-修改地址信息

<script type="text/javascript">
function showList() {
    var url = "../address/list.do";
    $.ajax({
        "url": url,
        "type": "GET",
        "dataType": "json",
        "success": function(json) {
            $("#address_list").empty();
            
            var addresses = json.data;
            for (var i=0; i < addresses.length; i++) {
                console.log(addresses[i].recvName + ", " + addresses[i].recvDistrict + ", " + addresses[i].recvAddress + ", " + addresses[i].isDefault);
                
                var html = '<div class="aim_content_one aim_active">'
                    + '<span class="dzmc dzmc_active">#{tag}</span>'
                    + '<span class="dzxm dzxm_normal">#{name}</span>'
                    + '<span class="dzxq dzxq_normal">#{address}</span>'
                    + '<span class="lxdh lxdh_normal">#{phone}</span>'
                    + '<span class="operation operation_normal">'
                    + ' <span class="aco_change">修改</span>|<span class="aco_delete">删除</span>'
                    + '</span>'
                    + '<span class="swmr swmr_normal"></span>'
                    + '</div>';
                    
                html = html.replace("#{tag}", addresses[i].recvTag);
                html = html.replace("#{name}", addresses[i].recvName);
                html = html.replace("#{address}", addresses[i].recvDistrict + addresses[i].recvAddress);
                html = html.replace("#{phone}", addresses[i].recvPhone);
                
                if (addresses[i].isDefault != 1) {
                    html = html.replace("dzmc_active", "dzmc_normal");
                    html = html.replace(" aim_active", "");
                }
            
                $("#address_list").append(html);
                
            }
        },
        "error": function(xhr, textStatus, errorThrown) {
            // xhr:XMLHttpRequest类型的对象
            // - responseText:响应的文本
            // - readyState:状态,值为0~4
            // - status:响应码
            console.log("状态码:" + xhr.readyState);
            console.log("响应码:" + xhr.status);
            console.log("响应文本:" + xhr.responseText);
            console.log("textStatus=" + textStatus);
            console.log("errorThrown=" + errorThrown);
        }
    });
}

showList();
</script>

猜你喜欢

转载自www.cnblogs.com/wood-life/p/10290874.html