java 如何在JDBC中执行多个查询并在三个结果集下获取它们

c9x0cxw0  于 2023-05-15  发布在  Java
关注(0)|答案(2)|浏览(186)

我想创建一个程序,将执行三个不同的查询和他们的结果将与用户名沿着邮寄在一个表格格式。下面是我设计的代码

public class SendNotification {
    public static void main(String[] args) throws SQLException, AddressException, MessagingException {
        // Database connection details
        String url = "jdbc:oracle:thin:@localhost:1521:XE";
        String user = "localuser";
        String password = "xxxxxx";
        //InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("config.properties");
        
        //User Details
        String user1 = "abUser";
        String user2 = "xyUser";
        String user3 = "cvUser";
        
        // SQL queries for each user
        String query1 = "SELECT COUNT(*) FROM dbtest WHERE AUTH = '" +user1+"' AND outdate >= SYSDATE - 7";
        String query2 = "SELECT COUNT(*) FROM dbtest WHERE AUTH = '" +user2+"' AND outdate >= SYSDATE - 7";
        String query3 = "SELECT COUNT(*) FROM dbtest WHERE AUTH = '" +user3+"' AND outdate >= SYSDATE - 7";
        
        // Create a connection to the database
        Connection connection = DriverManager.getConnection(url, user, password);
        
        // Create a statement and execute each query
        Statement statement = connection.createStatement();
        ResultSet resultSet1 = statement.executeQuery(query1);
        ResultSet resultSet2 = statement.executeQuery(query2);
        ResultSet resultSet3 = statement.executeQuery(query3);
        
        // Get the results and store them in a table
        Object[][] data = {
            {"User ID", "Document Count"},
            {user1, resultSet1.getInt(1)},
            {user2, resultSet2.getInt(1)},
            {user3, resultSet3.getInt(1)}
        };
        
     // Send an email with the results in tabular format
        String from = "devtest@ugc.local";
        String to = "PBxyz@gmail.com";
        
        String host = "mail.test.vb.xcv";
        
        Properties props = new Properties();
        props.put("mail.smtp.host", host);
        props.put("mail.smtp.port", "25");
        props.put("mail.debug", "true");
        
        Session session = Session.getDefaultInstance(props);
        MimeMessage message = new MimeMessage(session);
        message.setFrom(new InternetAddress(from));
        message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
        message.setSubject("Checked-In Document Counts");
        
        StringBuilder table = new StringBuilder();
        for (Object[] row : data) {
            table.append("<tr><td>").append(row[0]).append("</td><td>").append(row[1]).append("</td></tr>");
        }
        message.setText("<html><body><table>" + table.toString() + "</table></body></html>", "utf-8", "html");
        Transport.send(message);
        
        // Close the statement, result sets, and connection
        resultSet1.close();
        resultSet2.close();
        resultSet3.close();
        statement.close();
        connection.close();
    }
        

}

但是,我每次都遇到下面的错误。
线程“main”中出现异常java.sql.SQLException:关闭的结果集:getInt at oracle.jdbc.driver.GeneratedScrollableResultSet.getInt(GeneratedScrollableResultSet.java:237)at com.ura.SendNotification.main(SendTINNotification.java:48)
我该如何继续获得所需的输出?

0s0u357o

0s0u357o1#

你正在从相同的语句中访问结果集。这行不通。您可以创建Statements语句1、2和3的多个示例。然后相应地从每个示例访问结果集。最后,关闭所有连接、结果集和语句.

euoag5mw

euoag5mw2#

重新执行Statement关闭上一个ResultSet

你说:
java.sql.SQLException:关闭的结果集
一个Statement一次只能产生一个打开的ResultSet。再次执行该语句会自动关闭前一个ResultSet,同时生成后续的ResultSet
引用Javadoc for ResultSet(强调我的):
当生成ResultSet对象的Statement对象关闭、重新执行或用于从多个结果序列中检索下一个结果时,ResultSet对象将自动关闭。
请注意引用中的 re-executed 部分。

修改代码

下面是一个使用H2 Database Engine的完整示例应用程序。
使用集合进行软编码,而不是针对3个输入进行硬编码。
请注意我们是如何将报告与数据库查询分离的。通常最好保持这样的separation of concerns。这使我们能够避免您试图同时处理所有结果集的问题。在下面的代码中,我们将每个ResultSetput的结果收集到我们的Map中。我们将完整的Map返回给调用代码。然后调用代码将该Map传递给一个专门用于报告(或发送电子邮件,如您的问题中所示)的方法。
顺便说一下,我建议养成使用DataSource来包含数据库登录凭证的习惯。此接口使您的部署更加灵活,可以选择将此信息外部化到代码库之外。
请注意我们如何使用try-with-resourcesautomatically close,分别为ConnectionStatementPreparedStatementResultSet

package work.basil.example.db;

import org.h2.jdbcx.JdbcDataSource;

import javax.sql.DataSource;
import java.sql.*;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;

public class ExH2 {
    public static void main ( String[] args ) {

        ExH2 app = new ExH2 ( );
        DataSource dataSource = app.obtainDataSource ( );

        app.prepareDatabase ( dataSource );
        List < String > users = List.of ( "Alice" , "Bob" , "Carol" , "Davis" );
        app.populateDatabase ( dataSource , users );
        // app.dumpToConsole ( dataSource );
        Map < String, Integer > countPerUserForCurrentWeek = app.countPerUserForCurrentWeek ( dataSource , users );
        app.report ( countPerUserForCurrentWeek );
    }

    private DataSource obtainDataSource ( ) {
        org.h2.jdbcx.JdbcDataSource ds = new JdbcDataSource ( );  // An implementation of `javax.sql.DataSource` bundled with H2.
        ds.setURL ( "jdbc:h2:mem:history_db;DB_CLOSE_DELAY=-1" );
        ds.setUser ( "scott" );
        ds.setPassword ( "tiger" );
        ds.setDescription ( "An example database showing multiple result sets." );
        return ds;
    }

    private void prepareDatabase ( final DataSource dataSource ) {
        String sql =
                """
                        CREATE TABLE IF NOT EXISTS history_
                        (
                            user_ TEXT NOT NULL ,
                            when_ TIMESTAMP WITH TIME ZONE NOT NULL ,
                            id_ UUID NOT NULL DEFAULT RANDOM_UUID() ,
                            CONSTRAINT history_pkey_ PRIMARY KEY ( id_ )
                        )
                        ;
                        """;
        try (
                Connection conn = dataSource.getConnection ( ) ;
                Statement stmt = conn.createStatement ( ) ;
        ) {
            System.out.println ( "INFO - Running `prepareDatabase` method." );
            stmt.executeUpdate ( sql );
        } catch ( SQLException e ) {
            e.printStackTrace ( );
        }
    }

    private void populateDatabase ( final DataSource dataSource , List < String > users ) {
        String sql = """
                INSERT INTO history_ ( user_ , when_ )
                VALUES ( ? , ?)
                ;
                """;
        try
                (
                        Connection conn = dataSource.getConnection ( ) ;
                        PreparedStatement preparedStatement = conn.prepareStatement ( sql ) ;
                ) {
            for ( String user : users ) {
                int limit = ThreadLocalRandom.current ( ).nextInt ( 7 , 42 );
                System.out.println ( "user = " + user + " | limit = " + limit );
                for ( int i = 0 ; i < limit ; i++ ) {
                    preparedStatement.setString ( 1 , user );
                    preparedStatement.setObject ( 2 , OffsetDateTime.now ( ZoneOffset.UTC ) );
                    preparedStatement.executeUpdate ( );
                }
            }

        } catch ( SQLException e ) {
            e.printStackTrace ( );
        }
    }

    private void dumpToConsole ( DataSource dataSource ) {
        String sql = """
                SELECT *
                FROM history_
                ;
                """;
        try (
                Connection conn = dataSource.getConnection ( ) ;
                PreparedStatement preparedStatement = conn.prepareStatement ( sql ) ;
        ) {
//            preparedStatement.setString ( 1, "Carol" );
            try (
                    ResultSet resultSet = preparedStatement.executeQuery ( )
            ) {
                while ( resultSet.next ( ) ) {  // We expect a single row in each result set, for the count.
                    System.out.println (
                            resultSet.getString ( 1 ) + " | " +
                                    resultSet.getString ( 2 ) + " | " +
                                    resultSet.getString ( 3 ) + " | "
                    );
                }
            }
        } catch ( SQLException e ) {
            throw new RuntimeException ( e );
        }
    }

    private Map < String, Integer > countPerUserForCurrentWeek ( final DataSource dataSource , List < String > users ) {
        Map < String, Integer > map = new HashMap <> ( );
        String sql = """
                SELECT COUNT(*) 
                FROM history_
                WHERE user_ = ?
                AND when_ >= ? 
                AND when_ < ?
                ;
                """;
        try
                (
                        Connection conn = dataSource.getConnection ( ) ;
                        PreparedStatement preparedStatement = conn.prepareStatement ( sql ) ;
                ) {
            OffsetDateTime now = OffsetDateTime.now ( ZoneOffset.UTC );
            OffsetDateTime weekAgo = now.minusDays ( 7 );
            preparedStatement.setObject ( 2 , weekAgo );
            preparedStatement.setObject ( 3 , now );
            for ( String user : users ) {
                preparedStatement.setString ( 1 , user );
                try ( ResultSet resultSet = preparedStatement.executeQuery ( ) ) {
                    if ( resultSet.next ( ) ) {  // We expect a single row in each result set, for the count.
                        int count = resultSet.getInt ( 1 );
                        map.put ( user , count );
                    }
                }
            }
        } catch ( SQLException e ) {
            e.printStackTrace ( );
        }
        return Map.copyOf ( map );
    }

    private void report ( Map < String, Integer > countPerUserForCurrentWeek ) {
        System.out.println ( "countPerUserForCurrentWeek = " + countPerUserForCurrentWeek );
    }
}

运行时:

user = Alice | limit = 32
user = Bob | limit = 7
user = Carol | limit = 13
user = Davis | limit = 24
countPerUserForCurrentWeek = {Carol=13, Alice=32, Bob=7, Davis=24}

相关问题