图书管理系统总结——数据库操纵(三):数据库安全性

最后一次记录,说一说数据库的安全性。

一、一致性控制

为了保证事务的一致性,可以采用显示事务语句以及在数据库中添加完整性约束。比如在还书时候,要同时修改用户的用户表中的剩余借书本数,借阅记录中的已还选项以及图书表中剩余本数。这个时候可以有两个策略:

1、采用触发器,在MySQL中定义触发器:(仅举个例子)

DELIMITER $$

CREATE
    /*[DEFINER = { user | CURRENT_USER }]*/
    TRIGGER `db_book`.`Borrow` 
    AFTER INSERT
    ON `db_book`.`t_borrow`
    FOR EACH ROW BEGIN 
    UPDATE t_user SET borroNumRem=borrowNumRem-1 WHERE id=(SELECT userID FROM inserted);--修改用户表
    UPDATE t_book SET numer=number-1 WHERE id=(SELECT bookId FROM inserted);--修改图书表
    END$$

DELIMITER ;

2、在应用软件中做三个表修改

但是这样感觉出错了的话也不太好知道,最终采用在应用软件中分别对三个表进行操作。这样计算定期未还扣钱事件好操作一点,在应用程序里改参数还是比较习惯的。

二、并发控制

首先关于一个用户不能两次登录。如果是JAVA EE可以用web端的session:http://www.cnblogs.com/loveweiwei/p/4139668.html

但是这个由于不是网络,我也不知道怎么办,由于时间关系没空细致调研,只能用最低劣的方法,在user表中加一个属性表示是否登录。然后登录的函数中加一个行级锁,保证一个人抢先登录时候后面的人登录不进去这是就用到之前《数据库操纵(一)》中所定义的有关事务的函数:

/**
     * 登录验证
     * @param con
     * @param user
     * @return
     * @throws Exception
     */
    public User login(Connection con,User user)throws Exception
    {
        User resultUser=null;
        DbUtil dbUtil=new DbUtil();
        PreparedStatement pstmt = null;  
        ResultSet rs = null;  
        String sql="select * from t_user where id=? and password=? and IsLogin=? for update";//加悲观锁,不允许同时登陆
        try
        {    
            DbUtil.beginTransaction(con); //开始事务
            pstmt=con.prepareStatement(sql);
            //对问号设置
            pstmt.setString(1, user.getId());
            pstmt.setString(2, user.getPassword());
            pstmt.setByte(3, (byte)0);
            rs=pstmt.executeQuery();
            if(rs.next())
            {//如果查到了,则实例化
                resultUser=new User();
                resultUser.setId(rs.getString("id"));//getInt("id")
                resultUser.setUserName(rs.getString("userName"));
                resultUser.setPassword(rs.getString("password"));
                resultUser.setBorrowNumRem(rs.getInt("borrowNumRem"));
                resultUser.setBalance(rs.getFloat("balance"));
                resultUser.setIsLogin((byte)1);//置成已登陆
                int num=modifyIsLoginField(con,user.getId(),(byte)1);  
                //提交事务  
                DbUtil.commitTransaction(con);  
            }
      }catch(Exception e){  
          e.printStackTrace();  
          //回滚事务  
          DbUtil.rollbackTransaction (con);  
          throw new RuntimeException();  
      }finally{  
          DbUtil.close(rs);  
          DbUtil.close(pstmt);  
          DbUtil.resetTransaction(con);  
          dbUtil.closeCon(con);  
      }  
        return resultUser;
    }
    

同样,在缴纳用户费用时候也用了封锁机制。

/**
     * 用户缴纳罚款
     * @param tableName
     * @return
     */
    public static int Recharge(Connection con,User user)throws Exception
    {  
        //使用数据库的悲观锁for update  
        String sql = "select balance from t_user where id=? for update"; //加上for update为数据库加上行级排他锁,防止修改金额出错
        int num;    //update()返回条数                                                            
        DbUtil dbUtil=new DbUtil();
        PreparedStatement pstmt = null;  
        ResultSet rs = null;  
        float value = 0;  
        try{  
            //设置自动提交为false  
            DbUtil.beginTransaction(con);  

            pstmt = con.prepareStatement(sql);  
            pstmt.setString(1, user.getId());  
            rs = pstmt.executeQuery();             
            rs.next();  //指向第一条记录
            value = rs.getFloat("balance");  
            value=value+user.getBalance();//要求传进来的user为待增加的balance !
            user.setBalance(value);//改变balance
            num=modifyValueField(con,user.getId(),value);  
            //提交事务  
            DbUtil.commitTransaction(con);  
        }catch(Exception e){  
            e.printStackTrace();  
            //回滚事务  
            DbUtil.rollbackTransaction (con);  
            throw new RuntimeException();  
        }finally{  
            DbUtil.close(rs);  
            DbUtil.close(pstmt);  
            DbUtil.resetTransaction(con);  
            dbUtil.closeCon(con);  
        }  
        return num;  
    }  
    

由于时间关系,只对这两个重要事件加了锁。

 

posted @ 2017-05-14 18:35  satire  阅读(551)  评论(0编辑  收藏  举报