【问题标题】:Java: Using array as parameters conditions for inserting data to mysqlJava:使用数组作为向mysql插入数据的参数条件
【发布时间】:2020-01-21 04:25:29
【问题描述】:
package com.example.dev1.controller;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
/*import java.sql.ResultSet;*/
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;

import javax.swing.JApplet;

public class ReadLg extends JApplet {

    private static final long serialVersionUID = 1L;

    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        String[] lev_param = { "DEBUG", "WARN", "INFO", "ERROR" };
        List<String> listparam = Arrays.asList(lev_param);
        String temp = null;
        PreparedStatement ps = null;
        Connection con = null;
        /* ResultSet rs = null; */

        try {
            BufferedReader br = new BufferedReader(new FileReader("All.log"));
            String username = ****;
            String pwd = ****;
            String connurl = "jdbc:mysql://10.247.36.174:3306/d_accesslog?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC";

            con = DriverManager.getConnection(connurl, username, pwd);

            String line = null;
            while ((line = br.readLine()) != null) {
                temp+=line;
                if (line.equals(listparam)) {
                    String sql = "INSERT INTO t_weblogic_test (RawData) values ('\''+line+'\'')";
                    temp=null;
                } 

                ps = con.prepareStatement(sql);
                ps.executeUpdate();
            }

            br.close();
            con.close();
            ps.close();

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

所以,我对如何将数组作为参数条件插入有点困惑。
我想添加数组作为我的参数。在这个程序中,我读取日志数据并将日志级别设置为我的参数条件,因此当它读取下一个日志级别时,它将停止并将数据插入数据库。因此,我对如何做到这一点的确切方法有些困惑。

此日志文件如下所示
“调试 [CorporateUserSMImpl] 30-05-2019 00:01:04:id = 2c9dc30c673209d201675e3e5c961456”
“WARN [LoginAction] 30-05-2019 00:01:04:go MAIN 页面的登录过程 batchID = 2c9dc30c6ac6b815016b0452cd3d41ef 时间 ENDCALLBO= 2019-05-30 00:01:04.198”

所以当它读取下一个日志级别时,它将停止并保存上一行

新!!! 如果日志文件如下所示怎么办
“调试 [AccountDAOImpl] 30-05-2019 00:01:45: .....

开始调用getByAccountGroupIdAndIsInquiryPicklistWithAccountTypeNew 12方法
“调试 [AccountDAOImpl] 30-05-2019 00:01:45: currentPage =1

【问题讨论】:

    标签: java mysql arrays logging


    【解决方案1】:
    package com.example.dev1.controller;
    
    import java.io.BufferedReader;
    import java.io.FileReader;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.util.Arrays;
    import java.util.List;
    
    public class ReadLg3 {
        public static void main(String[] args) {
            String conn = "jdbc:mysql://ipaddress/d_accesslog?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC";
            String username = "****";
            String pwd = "****";
            String sql = "INSERT INTO t_weblogic_test (RawData) values (?)";
    
            String[] levParam = { "<DEBUG>", "<WARN", "<INFO", "<ERROR>","INFO", "WARN","DEBUG","ERROR" };
            List<String> listparam = Arrays.asList(levParam);
    
            try (Connection con = DriverManager.getConnection(conn, username, pwd);
                    PreparedStatement ps = con.prepareStatement(sql);
                    BufferedReader br = new BufferedReader(new FileReader("All.log"));) {
    
                String line = null;
                while ((line = br.readLine()) != null) {
                    String firstWord = line.split(" ", 2)[0];
                    if (listparam.contains(firstWord)) {
                        processMessages(line, br, listparam, ps);
                        break;
                    } else {
                        System.err.println("Failed!!");
                    }
                }
            } catch (Exception ex) {
                System.err.println("Error in \n" + ex);
            }
        }
    
        public static void processMessages(String line, BufferedReader br, List<String> listparam, PreparedStatement ps)
                throws Exception {
            StringBuilder message = new StringBuilder();
            message.append(line);
            while ((line = br.readLine()) != null) {
                String firstWord = line.split(" ", 2)[0];
                if (listparam.contains(firstWord)) {
                    ps.setString(1, message.toString());
                    ps.executeUpdate();
                    message.setLength(0);
                    message.append(line);
                } else {
                    message.append("\n" + line);
                }
            }
    
            if (message.length() > 0) {
                ps.setString(1, message.toString());
                ps.executeUpdate();
            }
        }
    }
    

    为了获得更高的性能,请使用字符串生成器

    【讨论】:

      【解决方案2】:

      您可以插入数组作为参数条件,通过替换sql来向MySQL插入数据,如下所述:

      String[] levParam = { "DEBUG", "WARN", "INFO", "ERROR" }; List listparam = Arrays.asList(levParam);

      while ((line = br.readLine()) != null) {
           String line=null;
      
                  String firstWord= line.split(" \\[")[0];
                  if(listparam.contains(firstWord)) { 
      
            processMessages(line, br, listparam, ps);
      
          }
      }
      
      
         private static void processMessages(String line, BufferedReader br, List<String> listparam, PreparedStatement ps) throws IOException, SQLException {
      String message = line;
      
      // Scan until the end of the message, eg the start of the next message
      while ((line = br.readLine()) != null) {
      
       String lastWord= s.split(" \\[")[1];
      
          // Insert your message
           String sql = "INSERT INTO t_weblogic_test (RawData) values ('\''+lastWord+'\'')";
             ps = con.prepareStatement(sql);
             ps.executeUpdate();
          message = line; // Start of the new message
      
      }
      

      【讨论】:

      • 谢谢,但我不是这个意思。我的意思是如何将数组作为参数。我的数组参数是我的日志级别,其中包含 {“DEBUG”、“WARN”、“INFO”、“ERROR”}。因此,当我读取日志文件时,它将读取每一行,并在读取日志级别时停止并保存上一行
      【解决方案3】:

      这里有一些需要优化的地方。您的具体问题是您将整行与无法工作的 ArrayList 进行比较:line.equals(listparam)。您应该获取行的第一个标记,看看您的列表是否包含这样的值。一种可能的方法是:

      String firstWord = line.split(" ",2)[0];
      if(listparam.contains(firstWord)) {
      
      }
      

      接下来,我建议使用 try-with-resources 构造来创建您的 conpsbr 资源。如果出现任何问题,这将自动关闭它们。此外,我将创建带有准备好的参数的 PreparedStatement 以最终传递日志消息,而不是仅将其连接到 sql 字符串中。这对性能会更好,因为您只需要创建一次语句,而且更安全。

      我在下面稍微重写了你的代码,这是未经测试的,所以可能仍然存在一些缺陷,但我希望你能大致了解:

      public static void main(String[] args) {
          String connurl = "jdbc:mysql://10.247.36.174:3306/d_accesslog?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC";
          String username = "****";
          String pwd = "****";
          // Use a prepared parameter in the sql string
          String sql = "INSERT INTO t_weblogic_test (RawData) values (?)";
      
          String[] levParam = { "DEBUG", "WARN", "INFO", "ERROR" };
          List<String> listparam = Arrays.asList(levParam);
      
          // Use a try-with-resources block to automatically handle the closing of the resources
          try(Connection con = DriverManager.getConnection(connurl, username, pwd); 
              PreparedStatement ps = con.prepareStatement(sql);
              BufferedReader br = new BufferedReader(new FileReader("All.log"));) {
      
            String line = null;
            while ((line = br.readLine()) != null) {
              // Get first token
              String firstWord = line.split(" ",2)[0];
              if(listparam.contains(firstWord)) { // Start of the first log message
                // Process all the messages from the log file
                processMessages(line, br, listparam, ps);
                break;
              }
            }
          } catch(SQLException ex) {
            // ex handling
          } catch(IOException ex) {
            // ex handling
          }
        }
      
        private static void processMessages(String line, BufferedReader br, List<String> listparam, PreparedStatement ps) throws IOException, SQLException {
          String message = line;
      
          // Scan until the end of the message, eg the start of the next message
          while ((line = br.readLine()) != null) {
            // Get first token
            String firstWord = line.split(" ",2)[0];
            if(listparam.contains(firstWord)) { // Start of the next log message
              // Insert your message
              ps.setString(1, message);
              ps.executeUpdate();
              message = line; // Start of the new message
            } else { // Continuation of the current message
              message = message.concat(line);
            }
          }
      
          if(!message.isEmpty()) {
            // Insert the last message from the log file
            ps.setString(1, message);
            ps.executeUpdate();
          }
        }
      

      【讨论】:

      • 感谢您的回复。我对 SQL 的工作原理有点困惑。您将值更改为(?)。那么它将在哪个会话中将字符串中的值插入到数据库中?
      • sql中使用的问号是参数占位符。 ps.setString(1, message) 将确保驱动程序将参数替换为字符串形式的消息。 '1' 表示您要替换第一个参数。这样,您可以在 sql 字符串中使用多个参数,并使用 ps.setString()ps.setInt()、... 方法来设置这些参数的值。这个系统确保语句只需要编译一次,因为只有参数值改变而不是整个 sql 字符串。它还可以防止 sql 注入,因为驱动程序会处理参数的替换。
      • 我希望这能说明一点,但也请查看link 了解更多信息。
      • 谢谢你.. 如果你不介意 line.split(" ",2)[0].. 如何阅读这行代码,我想问最后一个问题?
      • 这将根据“”分隔符分割行,因此在每个空格之后,并将结果存储在一个数组中。 '2' 表示结果数组的大小,因为在这种情况下我们只需要第一个单词,2 就足够了。结果数组的索引 0 将包含我们的第一个单词,数组的索引 1 将包含该行的其余部分。如果省略限制参数 ('2'),则结果数组将包含每个单独单词的条目。
      猜你喜欢
      • 2021-12-20
      • 1970-01-01
      • 1970-01-01
      • 2019-11-17
      • 1970-01-01
      • 2017-01-30
      • 2013-11-17
      • 1970-01-01
      • 2022-11-11
      相关资源
      最近更新 更多