0

データベース内に 3 つのテーブルがあります。1 つはemployee、2 番目はemployee_Project、3 番目はemployee_Reportingです。各テーブルには共通employee_Numberの主キーがあり、それらの間には 1 対多の関係があり、1 人の従業員が多くのプロジェクトと報告日を持っています。

メソッドとを持つ 3 つのデータ ホルダー クラスで、、、をselect * from employee実行select * from employee_projectしました。これはメソッドを持つクラスに 基づいており、実装が完了しています。select * from employee_reportingfillResultSet(Result set)List<T> getData()SqlDbEnginerunQuery(PreparedStatement,DataHolder)

getAllEmployee()ここで、JDBC を使用して Java で最適なコードを使用して、プロジェクトとレポートの詳細と共にメソッドを設計する必要があります。イテレータを使用しましたが、この解決策は受け入れられません。今度は foreach ループを使用する必要があります。

これは私がやったことです:

public List<Employee> getAllEmployees() {
    EmployeeDataHolderImpl empdataholder = new EmployeeDataHolderImpl();
    List<Employee> list_Employee_Add = null;

    try {
        Connection connection = mySqlDbConnection.getConnection();
        PreparedStatement preparedStatement = connection
                .prepareStatement(GET_ALL_EMPLOYEE_DETAILS);
        mySqlDBEngineImpl.runQuery(preparedStatement, empdataholder);
    } catch (SQLException e) {

        e.printStackTrace();
    }
    for (Employee employee : empdataholder.getData()) {
        new EmployeeDAOImpl().getProject(employee);
                    new EmployeeDAOImpl.getReport(employee);
    }
    list_Employee_Add = empdataholder.getData();
    return list_Employee_Add;

}

そして別の方法を作る

    public void getProject(Employee emp) {
    EmployeeProjectDataHolderImpl employeeProjectHolder = new EmployeeProjectDataHolderImpl();
    try {
        Connection connection = mySqlDbConnection.getConnection();
        PreparedStatement preparedStatement = connection
                .prepareStatement(GET_ALL_PROJECT_DETAILS);
        mySqlDBEngineImpl
                .runQuery(preparedStatement, employeeProjectHolder);
    } catch (SQLException e) {
        e.printStackTrace();
    }
    for (EmployeeProject employee_Project : employeeProjectHolder.getData()) {
        if (employee_Project.getEmployeeNumber() == emp.getEmpNumber()) {
            emp.getProjects().add(employee_Project);
        }
    }
}

    public void getReport(Employee emp) {
    EmployeeReportDataHolderImpl employeeReportHolder = new EmployeeReportDataHolderImpl();
    try {
        Connection connection = mySqlDbConnection.getConnection();
        PreparedStatement preparedStatement = connection
                .prepareStatement(GET_ALL_REPORT_DETAILS);
        mySqlDBEngineImpl
                .runQuery(preparedStatement, employeeReportHolder);
    } catch (SQLException e) {
        e.printStackTrace();
    }
    for (EmployeeReport employee_Report : employeeReportHolder.getData()) {
        if (employee_Report.getEmployeeNumber() == emp.getEmpNumber()) {
            emp.getProjects().add(employee_Project);
        }
    }
}
}

従業員レポートについても同じですが、このパフォーマンスは低下します。接続を閉じる心配はありません。私はそれを行います

どうすれば解決策を改善できるか教えてください..

4

4 に答える 4

1

コードに問題があります。

1.毎回 EmployeeDAOImpl を初期化していますが、インスタンスを 1 つだけ保持して、その上で操作を呼び出すことができます。

new EmployeeDAOImpl().getProject(従業員); 新しい EmployeeDAOImpl.getReport(従業員);

2.SQL 操作の実行後に接続を閉じる場所がわかりません。

于 2012-10-23T07:42:03.603 に答える
1

あなたが持っている必要があります

try {

--code statements 

}
catch(SQLException e){
e.printStackTrace();
}
finally{
-- close your connection and preparedStatement
}

データベース接続を閉じることは非常に重要です。

于 2012-10-23T08:07:41.543 に答える
0

私の理解が正しければ、あなたのコードは最初にすべてのEmployeeReport行をロードし、次に に従ってそれらをフィルタリングしますgetEmployeeNumber()。SQL クエリを変更することで、データベースにこれを実行させることができます。

あなたはあなたのSQLクエリを表示していないので(私はそれらがGET_ALL_REPORT_DETAILS.

select *
from employee_reporting
where employeeNumber = ?

これを に入れPreparedStatementてパラメータ値を設定すると、データベースは必要なデータのみを返します。例えば:

PreparedStatement pstmt = con.prepareStatement(GET_ALL_REPORT_DETAILS);
pstmt.setInt(1, employee.getEmployeeNumber());

EmployeeReportそれは、目的の を持つレコードのみを返す必要がありますemployeeNumber。パフォーマンスがまだ問題である場合は、テーブルにインデックスを追加することを検討できますがEmployeeReport、それは別の話です...

于 2012-10-23T08:03:29.833 に答える
0

実際のコードを使用すると、コードに 3 つの影響があります。

  • 従業員のデータを取得するために接続を開いています。
  • すべての従業員に対して、新しい接続を開いて (そして閉じて) 彼のプロジェクトを取得します。
  • すべての従業員について、レポートを取得するために新しい接続を開きます (そして閉じます)。

新しい接続を開くと、アプリケーションのパフォーマンスが低下することに注意してください。強化された for ループまたは Iterator を使用するかどうかは関係ありません。アプリケーションの速度を低下させる可能性のある多くのヒットがあります。

この問題を解決するには、次の 2 つの方法があります。

  1. すべての select ステートメントを実行する単一の接続を開きます。これは、多くの接続を開閉するよりも優れています。

  2. 単一の SQL ステートメントを作成して、従業員と、すべての従業員に必要なデータを取得します。さまざまな理由でパフォーマンスが向上します。

    • データベースへの単一接続。
    • データベースへの多数のクエリではなく、単一のクエリ (単一の I/O 操作)。
    • rdbms で許可されている場合、クエリは将来のリクエスト用に最適化されます (複数のクエリではなく単一のクエリ)。

2番目のオプションを使用したいと思います。このために、SQL select ステートメントを実行して ResultSet を返すメソッドを使用する傾向があります。基本的な例を投稿します (提供されたコードは必要に応じて改善できることに注意してください)。このメソッドはSqlDbEngineクラス内にある可能性があります。

public ResultSet executeSQL(Connection con, String sql, List<Object> arguments) {
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    try {
        pstmt = con.prepareStatement(sql);
        if (arguments != null) {
            int i = 1;
            for(Object o : arguments) {
                pstmt.setObject(i++, o);
            }
        }
        //method to execute insert, update, delete statements...
        rs = pstmt.execute();
    } catch(SQLException e) {
        //handle the error...
    }
    return rs;
}

そして、すべてのクエリ操作を処理するこの他の方法

public List<Employee> getAllEmployee() {
    Connection con = null;
    ResultSet rs = null;
    List<Employee> lstEmployee = new ArrayList<Employee>();
    try {
        con = mySqlDbConnection.getConnection();
        //write the sql to retrieve all the data
        //I'm assuming these can be your columns, it's up to you
        //this can be written using JOINs...
        String sql = "SELECT E.EMPLOYEE_ID, E.EMPLOYEE_NAME, P.PROJECT_NAME, R.REPORT_NAME FROM EMPLOYEE E, PROJECT P, REPORT R WHERE E.EMPLOYEE_ID = P.EMPLOYEE_ID AND E.EMPLOYEE_ID = R.EMPLOYEE_ID";
        //I guess you don't need parameters for this...
        rs = SqlDbEngine.executeSQL(con, sql, null);
        if (rs != null) {
            Employee e;
            int employeeId = -1, lastEmployeeId = -1;
            while (rs.next()) {
                //you need to make sure to create a new employee only when
                //reading a new employee id
                employeeId = rs.getInt("EMPLOYEE_ID");
                if (lastEmployeeId != employeeId) {
                    e = new Employee();
                    lastEmployeeId = employeeId;
                    lstEmployee.add(e);
                }
                Project p = new Project();
                Report r = new Report();
                //fill values of p...
                //fill values of r...
                //you can fill the values taking advantage of the column name in the resultset
                //at last, link the project and report to the employee
                e.getProjects().add(p);
                e.getReports().add(r);
            }
        }
    } catch (Exception e) {
        //handle the error...
    } finally {
        try {
            if (rs != null) {
                Statement stmt = rs.getStatement();
                rs.close();
                stmt.close();
            }
            if (con != null) {
                con.close();
            }
        } catch (SQLException e) {
            //handle the error...
        }
    }
    return lstEmployee;
}

2 番目の方法はコーディングが難しくなる可能性がありますが、最高のパフォーマンスが得られることに注意してください。提供されたメソッドを改善するのはあなた次第です。いくつかのアドバイス:

  • ResultSet を受け取り、ResultSet の列名を使用してインスタンスを構築するクラスを作成します(および とProject同様)。ReportEmployee
  • ResultSetとそのStatementクローズを処理するメソッドを作成します。
  • ベスト プラクティスとして、は使用しないselect * from mytableでください。必要な列を書き込むことをお勧めします。
于 2012-10-23T08:09:14.800 に答える