package sample;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import entity.Employee;

/**
 * JDBC版従業員DataAccessObject
 */
public class JdbcEmployeeDAO {

    /**
     * JDBCコネクション
     */
    private Connection connection;
    
    /**
     * コンストラクタ
     * @param connection JDBCコネクション
     */
    public JdbcEmployeeDAO(Connection connection){
        this.connection = connection;
    }

    /**
     * 指定したIDの従業員を取得する
     * @param id 従業員ID
     * @param lock 行ロックを行うかどうか
     * @return
     * @throws SQLException
     */
    public Employee get(int id, boolean lock) throws SQLException{
        String sql = "SELECT * FROM EMPLOYEES WHERE ID = ?";
        if( lock ){
            sql += " FOR UPDATE";
        }

        // ステートメントオブジェクトを生成
        PreparedStatement stmt = connection.prepareStatement(sql);
        stmt.setInt(1, id);
        // クエリーを実行して結果セットを取得
        ResultSet rs = stmt.executeQuery();
        
        Employee emp = null;
        if(rs.next()){
            //従業員オブジェクトを生成(部門オブジェクトは省略)
            emp = new Employee(new Integer(rs.getInt("ID")),
                                rs.getString("NAME"),
                                new Integer(rs.getInt("SALARY")),
                                new Integer(rs.getInt("DEPARTMENT_ID")),
                                null);
        }
        
        // データベースから切断
        stmt.close();
        
        return emp;
    }
    
    /**
     * 部門名に対応する従業員のリストを取得する
     * @param departmentName 部門名
     * @param lock 行ロックを行うかどうか
     * @return List
     * @throws SQLException
     */
    public List getListByDepartmentName(String departmentName, boolean lock) throws SQLException{
        String sql = "SELECT EMPLOYEES.* FROM EMPLOYEES"
                    +" INNER JOIN DEPARTMENTS ON EMPLOYEES.DEPARTMENT_ID = DEPARTMENTS.ID"
                    +" WHERE DEPARTMENTS.NAME = ?";
        if( lock ){
            sql += " FOR UPDATE";
        }
        // ステートメントオブジェクトを生成
        PreparedStatement stmt = connection.prepareStatement(sql);
        stmt.setString(1, departmentName);
        // クエリーを実行して結果セットを取得
        ResultSet rs = stmt.executeQuery();

        List list = new ArrayList();
        // 検索された行数分ループ
        while(rs.next()){
            //従業員オブジェクトを生成(部門オブジェクトは省略)
            Employee emp = new Employee(new Integer(rs.getInt("ID")),
                                        rs.getString("NAME"),
                                        new Integer(rs.getInt("SALARY")),
                                        new Integer(rs.getInt("DEPARTMENT_ID")),
                                        null);
            list.add(emp);
        }

        // データベースから切断
        stmt.close();

        return list;
    }

    /**
     * 従業員を挿入する
     * @param emp 従業員
     * @throws SQLException
     */
    public void insert(Employee emp) throws SQLException{
        String sql = "INSERT INTO EMPLOYEES (ID, NAME, SALARY, DEPARTMENT_ID)"
                    +" VALUES(?, ?, ?, ?)";
        // ステートメントオブジェクトを生成
        PreparedStatement stmt = connection.prepareStatement(sql);
        stmt.setInt(1, emp.getId().intValue());
        stmt.setString(2, emp.getName());
        stmt.setInt(3, emp.getSalary().intValue());
        stmt.setInt(4, emp.getDepartmentId().intValue());
        //ステートメントの実行
        stmt.execute();
        
        // データベースから切断
        stmt.close();

    }
    
    /**
     * 従業員を削除する
     * @param emp 従業員
     * @throws SQLException
     */
    public void delete(Employee emp) throws SQLException{
        String sql = "DELETE FROM EMPLOYEES WHERE ID = ?";
        // ステートメントオブジェクトを生成
        PreparedStatement stmt = connection.prepareStatement(sql);
        stmt.setInt(1, emp.getId().intValue());
        //ステートメントの実行
        stmt.execute();
        
        // データベースから切断
        stmt.close();

    }

    /**
     * 従業員を更新する
     * @param emp 従業員
     * @throws SQLException
     */
    public void update(Employee emp) throws SQLException{
        String sql = "UPDATE EMPLOYEES SET"
            +" NAME = ?, SALARY = ?, DEPARTMENT_ID = ?"
            +" WHERE ID = ?";
        // ステートメントオブジェクトを生成
        PreparedStatement stmt = connection.prepareStatement(sql);
        stmt.setString(1, emp.getName());
        stmt.setInt(2, emp.getSalary().intValue());
        stmt.setInt(3, emp.getDepartmentId().intValue());
        stmt.setInt(4, emp.getId().intValue());
        //ステートメントの実行
        stmt.execute();
        
        // データベースから切断
        stmt.close();

    }

    /**
     * サンプルコードメイン
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception{
        Connection con = null;
        try {
            // ドライバクラスをロード
            Class.forName("org.gjt.mm.mysql.Driver");
              
            // データベースへ接続
            String url = "jdbc:mysql:///ogis";
            con = DriverManager.getConnection(url,"root",null);
            con.setAutoCommit(false);
            
            JdbcEmployeeDAO dao = new JdbcEmployeeDAO(con);

            //IT部門の従業員を取得
            List list = dao.getListByDepartmentName("IT", true);

            //給与を1000円値上げ
            Iterator ite = list.iterator();
            while(ite.hasNext()){
                Employee emp = (Employee) ite.next();
                int salary = emp.getSalary().intValue();
                emp.setSalary( new Integer(1000 + salary) );
                
                //従業員の更新
                dao.update(emp);
            }

            //コミット
            con.commit();
        } catch (Exception e) {
            //ロールバック
            if(con != null){
                con.rollback();
            }
            e.printStackTrace();
        }finally{
            //コネクションは常に閉じる
            if(con != null){
                con.close();
            }
        }
    }
}