0

我的数据库中有这些表。一是employee,二是employee_Project,三是employee_Reporting。每个表都有一个公共employee_Number作为其主键,并且它们之间存在一对多的关系,因此员工有许多项目和报告日期。

我已经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,而您可以只保留一个实例并调用它的操作。

new EmployeeDAOImpl().getProject(employee); new EmployeeDAOImpl.getReport(employee);

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),所以我只是猜测...尝试执行 SQL,如下所示:

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 循环还是迭代器,都会有很多点击会减慢您的应用程序的速度。

解决这个问题的两种方法:

  1. 打开一个运行所有选择语句的连接。这比打开/关闭大量连接要好。

  2. 创建单个 SQL 语句来检索员工以及每个员工所需的数据。由于不同的原因,它将具有更好的性能:

    • 与数据库的单个连接。
    • 单个查询而不是对数据库的大量查询(单个 I/O 操作)。
    • 如果您的 rdbms 允许,查询将针对未来的请求进行优化(单个查询而不是多个查询)。

我宁愿选择第二种选择。为此,我倾向于使用执行任何 SQL 选择语句并返回 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;
}

请注意,第二种方式可能更难编码,但它会为您提供最佳性能。您可以改进提供的方法,一些建议:

  • 创建一个接收 ResultSet 并Project使用 ResultSet 的列名称构建实例的类(类似于ReportEmployee)。
  • 创建一个处理 theResultSet及其Statement关闭的方法。
  • 作为最佳实践,永远不要使用select * from mytable,最好编写所需的列。
于 2012-10-23T08:09:14.800 回答