看购物车代码时的两个疑问

[size=large]以下是孙鑫老师书上的代码有几个地方不明白。[/size]

[code="java"]
package org.sunxin.ch09.bookstore;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

public class BookDBBean implements Serializable {

private DataSource ds = null;


public BookDBBean() throws NamingException {
    Context ctx = new InitialContext();
    ds = (DataSource)ctx.lookup("java:comp/env/jdbc/bookstore");
}


public Connection getConnection() throws SQLException {

    return ds.getConnection();

}


protected void closeConnection(Connection conn) {
    if(conn!=null) {
        try {
            conn.close();
            conn = null;
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}


protected void closeStatement(Statement stmt) {
    if(stmt != null) {
        try {
            stmt.close();
            stmt = null;
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}


protected void closePreparedStatement(PreparedStatement pstmt) {
    if(pstmt != null) {
        try {
            pstmt.close();
            pstmt = null;
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}


protected void closeResultSet(ResultSet rs) {
    if(rs != null) {
        try {
            rs.close();
            rs = null;
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}


public Collection<BookBean> getBooks() throws SQLException {


    Connection conn = null;
    Statement stmt = null;
    ResultSet rs = null;


    try {
        Collection<BookBean> bookList = new ArrayList<BookBean>();
        conn = this.getConnection();
        stmt = conn.createStatement();
        rs = stmt.executeQuery("select * from bookinfo");

        while(rs.next()) {
            BookBean book = new BookBean(rs.getInt(1), rs.getString(2), rs.getString(3), rs.getString(4),
                            rs.getString(5), rs.getFloat(6), rs.getInt(7), rs.getString(8));
            bookList.add(book);
        }
        return bookList;

    } finally {
        closeResultSet(rs);
        closeStatement(stmt);
        closeConnection(conn);
    }

}   


public BookBean getBook(int bookId) throws SQLException {

    Connection conn = null;
    PreparedStatement pstmt = null;
    ResultSet rs = null;

    try {

        conn = getConnection();
        pstmt = conn.prepareStatement("select * from bookinfo where bookId = ?");
        pstmt.setInt(1, bookId);
        rs = pstmt.executeQuery();
        BookBean book = null;

        if(rs.next()) {
            book = new BookBean(rs.getInt(1), rs.getString(2), rs.getString(3), rs.getString(4),
                    rs.getString(5), rs.getFloat(6), rs.getInt(7), rs.getString(8));
        }

        return book;

    } finally {
        closeResultSet(rs);
        closePreparedStatement(pstmt);
        closeConnection(conn);
    }
}


public Collection<BookBean> searchBook(String keyword)throws SQLException {
    Connection conn = null;
    Statement stmt = null;
    ResultSet rs = null;

    ArrayList<BookBean> bookList = new ArrayList<BookBean>();

    try {

        conn = getConnection();
        stmt = conn.createStatement();
        String sql = "select * from bookinfo where title like " + "'%" + keyword + "%'";
        rs = stmt.executeQuery(sql);

        while(rs.next()) {
            BookBean book = new BookBean(rs.getInt(1), rs.getString(2), rs.getString(3), rs.getString(4),
                    rs.getString(5), rs.getFloat(6), rs.getInt(7), rs.getString(8));
            bookList.add(book);
        }

        return bookList;


    } finally {
        closeResultSet(rs);
        closeStatement(stmt);
        closeConnection(conn);
    }   
}


public boolean isAmountEnough(int bookId, int quantity) throws SQLException{

    Connection conn = null;
    Statement stmt = null;
    ResultSet rs = null;
    boolean bEnough = false;

    try {

        conn = getConnection();
        stmt = conn.createStatement();
        String sql = "select amount from bookinfo where id = " + bookId;
        rs = stmt.executeQuery(sql);

        if(rs.next()) {
            int amount = rs.getInt(1);
            if(amount >= quantity) {
                bEnough = true;
            }
        }

        return bEnough;

    } finally {
        closeResultSet(rs);
        closeStatement(stmt);
        closeConnection(conn);
    }   
}



public synchronized void buyBooks(CartBean cart) throws SQLException{

    Connection conn = null;
    PreparedStatement pstmt = null;
    Iterator<CartItemBean> it = cart.getItems().iterator();

    try {

        conn = this.getConnection();
        String sql = "update bookinfo set amount = amount - ? where id = ?";
        pstmt = conn.prepareStatement(sql);

        while(it.hasNext()) {
            CartItemBean item = it.next();
            BookBean book = item.getBook();
            int bookId = book.getId();
            int quantity = item.getQuantity();

            pstmt.setInt(1, quantity);
            pstmt.setInt(2, bookId);

            pstmt.addBatch();
        }   
        pstmt.executeBatch();

    } finally {
        this.closePreparedStatement(pstmt);
        this.closeConnection(conn);
    }   
}

}
[/code]

[size=large][color=red]
1.为何不定义成员变量 private Connection conn;呢? 是出于安全考虑吗?
2.为何在关闭连接的处理中对异常做了处理,而在其他的方法中却要将异常抛出呢?
抛出有什么好处呢?(这个问题请将详细些吧。琢磨好长时间了。异常基础知识看了一遍又一遍,还是不理解为什么这样用)

[/color]

[quote]1.为何不定义成员变量 private Connection conn;呢? 是出于安全考虑吗?[/quote]
关于这一点,是为了线程安全。当系统里面有多个请求同时进行的时候,要保证使用的不是同一个连接,这样不会影响到事务处理。

[quote]2.为何在关闭连接的处理中对异常做了处理,而在其他的方法中却要将异常抛出呢?
抛出有什么好处呢?(这个问题请将详细些吧。琢磨好长时间了。异常基础知识看了一遍又一遍,还是不理解为什么这样用) [/quote]

关闭连接的异常对于服务的使用者来说是没有必要知道的。把信息返回没有任何的价值,所以直接在内部消化掉。

但是其他方法中的数据库CRUD操作失败的情况是需要返回给使用者的。所以要向上层抛出,最后由UI层统一处理掉。

buaalijie 回答的很清楚了