数据库开发 - 事务单元做业

#问题 1(100分)有一个在线交易电商平台,有两张表,分别是库存表和订单表,以下:java

输入图片说明

如今买家XiaoMing在该平台购买bag一个,须要同时在库存表中对bag库存记录减一,同时在订单表中生成该订单的相关记录。 请编写Java程序,实现XiaoMing购买bag逻辑。订单表ID字段为自增字段,无需赋值。mysql

#解答 ##购买事务逻辑 XiaoMing购买bag一个,首先检查是否还有剩余库存,若是有库存,则进行购买,若是没有库存,返回没有库存异常。当有库存时,对库存表中的记录减一,并生成订单记录。 ##事务与锁的分析 这里必须进行加锁,否则会发生各类问题,经过查阅相关资料,肯定悲观锁,是相对稳健的形式。 ##初始化数据库 homework.sqlsql

CREATE TABLE `inventory` (
`ID`  int NOT NULL AUTO_INCREMENT ,
`ProductName`  varchar(100) NULL ,
`Inventory`  int NULL ,
PRIMARY KEY (`Id`)
);

INSERT INTO `inventory` (`ID`, `ProductName`, `Inventory`) VALUES ('1', 'watch', '25');
INSERT INTO `inventory` (`ID`, `ProductName`, `Inventory`) VALUES ('2', 'bag', '20');

CREATE TABLE `order` (
`ID`  int NOT NULL AUTO_INCREMENT ,
`buyer`  varchar(100) NULL ,
`ProductName` varchar(100) NULL ,
PRIMARY KEY (`Id`)
);

##执行测试类数据库

package com.hava.transition;

import junit.framework.TestCase;

/**
 * Created by zhanpeng on 2016/10/8.
 */
public class OrderDAOTest extends TestCase {
    public void testTransferAccount() throws Exception {
        OrderDAO orderDAO = new OrderDAO();
        orderDAO.init();
        orderDAO.buyOne("XiaoMing","bag");
    }
}

##数据库访问类apache

package com.hava.transition;

import org.apache.commons.dbcp2.BasicDataSource;

import java.sql.*;

/**
 * Created by zhanpeng on 2016/10/8.
 */
public class OrderDAO {

    public static BasicDataSource basicDataSource = null;

    public final static String JDBC_DRIVER = "com.mysql.jdbc.Driver";
    public final static String DB_URL = "jdbc:mysql://192.168.1.200/test";
    public final static String USER = "root";
    public final static String PASSWORD = "dVHJtG0T:pf*";

    public void init()
    {
        basicDataSource = new BasicDataSource();
        basicDataSource.setUrl(DB_URL);
        basicDataSource.setDriverClassName(JDBC_DRIVER);
        basicDataSource.setUsername(USER);
        basicDataSource.setPassword(PASSWORD);
    }

    public void buyOne(String buyer,String productName) throws ClassNotFoundException {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            connection = basicDataSource.getConnection();
            //开启事务
            connection.setAutoCommit(false);
            //使用悲观锁
            String getproduct_sql = "SELECT Inventory FROM inventory WHERE(ProductName = ?) FOR UPDATE";
            preparedStatement = connection.prepareStatement(getproduct_sql);
            preparedStatement.setString(1,productName);
            resultSet = preparedStatement.executeQuery();
            int inventory = -1;
            while(resultSet.next())
                inventory = resultSet.getInt("Inventory");

            System.out.println("[inventory]:" + inventory);

            if(inventory <= 0)
            {
                System.out.println("没有库存");
                throw new SQLException();
            }
            else
            {
                //减小库存
                String subproduct_sql = "UPDATE inventory SET Inventory=? WHERE (ProductName = ?)";
                preparedStatement = connection.prepareStatement(subproduct_sql);
                preparedStatement.setInt(1,inventory - 1);
                preparedStatement.setString(2,productName);
                preparedStatement.execute();

                //新增订单
                String addorder_sql = "INSERT INTO `order` (`buyer`, `ProductName`) VALUES (?, ?)";
                preparedStatement = connection.prepareStatement(addorder_sql);
                preparedStatement.setString(1,buyer);
                preparedStatement.setString(2,productName);
                preparedStatement.execute();

                //提交事务
                connection.commit();
            }




        } catch (SQLException e) {
            // ignore
            System.out.println("[SQLException]:" + e.toString());
            //若是发生异常则回滚事务
            if(connection != null)
                try {
                    //发生异常回滚
                    connection.rollback();

                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
        } finally {
            if (preparedStatement != null)
            {
                try {
                    preparedStatement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

#参考文献 mysql处理高并发,防止库存超卖
电商 对于特定数量的商品 如何在高并发下进行库存锁定呢?
订单系统中并发问题和锁机制的探讨
企业应用架构模式架构

相关文章
相关标签/搜索