java - 如何将字符串写入容器以在循环后使用?

标签 java mysql io

我有一个应用程序,它创建多个查询(更新或插入),然后执行每个查询。

整个代码工作正常,但我发现在此过程中我的服务器 IO 延迟太多。

代码执行一个循环,大约需要 1 分钟。

然后我想做的是将每个查询写入内存中而不是执行它,然后,一旦我有了要执行的整个查询列表,就使用 mysql 中的“LOAD DATA LOCAL INFILE”,这将花费更少的时间。

我的问题是:如何在 java 中的"file"或“任何其他容器”中编写所有查询(字符串对象)以便在循环后使用它?

@user3283548这是我的示例代码:

第一类:

import java.util.ArrayList;

public class Class1 {



public static void main(String[] args) throws Exception {
    // TODO Auto-generated method stub

    ArrayList<String> Staff=new ArrayList<String>();
    Staff.add("tom");
    Staff.add("Laura");
    Staff.add("Patricia");
     for (int x = 0; x < Staff.size(); x++) {
         System.out.println(Staff.get(x));
         Class2 user = new Class2 (Staff.get(x));
         user.checkUser();

     }
}

}

2级:

public class Class2 {

private String user;

 public Class2(String user){
     this.user=user;
 }
 public void checkUser() throws Exception{

 if (user.equals("tom")){
         String queryUser="update UsersT set userStatus='2' where UserName='"+user+"';";
         Class3 updateUser = new Class3(queryUser);
         updateUser.UpdateQuery();;
 }else{
         String queryUser="Insert into UsersT (UserName,userStatus)Values('"+user+"','1');";
         Class3 updateUser = new Class3(queryUser);
         updateUser.InsertQuery();
         System.out.println(user+" is not ton doing new insert");
 }

 }   
}

第三类:

 public class Class3 {
    public String Query;

    public Class3(String Query){
        this.Query = Query;
    }

    public void UpdateQuery() throws Exception{ 

    /*// Accessing Driver From Jar File
    Class.forName("com.mysql.jdbc.Driver");
    //DB Connection
    Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/default","root","1234567");
    String sql =Query;
    PreparedStatement pst = con.prepareStatement(sql);*/

    System.out.println(Query); //Just to test

    //pst.execute();
}
    public void InsertQuery() throws Exception{ 

        /*// Accessing Driver From Jar File
        Class.forName("com.mysql.jdbc.Driver");
        //DB Connection
        Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/default","root","1234567");
        String sql =Query;
        PreparedStatement pst = con.prepareStatement(sql);*/

        System.out.println(Query); //Just to test

        //pst.execute();
    }
}

然后,我想做的是在 Class1 中创建一个 ArraList 并在 Class3 中使用它来收集所有必须执行的查询。

这个想法是在主进程完成后一次性执行查询列表,而不是对 Class1 循环中的每个元素执行此操作。我想这样做,因为我认为这会减少服务器 HD 的资源 IO

最佳答案

您的循环可能太慢,因为您正在使用 String 构建字符串

我猜测你正在做类似的事情

字符串查询 = "SELECT * FROM "+ 变量a + "WHERE + 变量b + "= "...

如果您要进行大量字符串连接,请使用StringBuilder,因为每次更改字符串时,它实际上都会重新创建,这是昂贵的。只需更改代码以使用 StringBuilder 而不是字符串,可能会将循环执行时间缩短到几毫秒。只需调用StringBuilder obj.toString()方法即可获取字符串。

存储对象

如果您想存储任何内容以供以后使用,您应该将其存储在集合中。如果您想要键值关系,请使用 Map (HashMap 很适合您)。如果您只想要值,请使用 List(ArrayList 最受欢迎)。

例如,如果我想存储查询字符串以供以后使用,我会...

  1. 使用 StringBuilder 构造字符串。
  2. 将字符串(通过调用 .toString() 放入 HashMap
  3. 从 HashMap 中获取查询字符串...

如果您不需要在应用程序重新启动时保留它们,那么您永远不应该将它们存储在磁盘上,即使如此,我也会将它们存储在数据库中而不是文件中。

希望这有帮助。

谢谢

大卫

编辑:根据您发布的代码进行更新:

好的,这需要一些重大的重构!

我一直保持简单,因为我没有太多时间全面重写。

我已经评论了我更正的地方。

这里的主要问题是在循环中创建对象。您应该只创建一次对象,因为创建对象的成本很高。

我还纠正了其他编码问题并替换了 for 循环,因为您不应该这样编写它。我还将这些类重命名为有用的名称。

我尚未对此进行测试,因此您可能需要做一些工作才能使其正常工作。但这应该会快很多。

旧 1 类

import java.util.ArrayList;
import java.util.List;

public class StaffChecker {


public static void main(String[] args) throws Exception {

    // Creating objects is expensive, you should do this as little as possible
    StaffCheckBO staffCheckBO = new StaffCheckBO();

    // variables should be Camel Cased and describe what they hold
    // Never start with ArrayList start with List you should specific the interface on the left side.
    List<String> staffList = new ArrayList<String>();
    staffList.add("tom");
    staffList.add("Laura");
    staffList.add("Patricia");

    // use a foreach loop not a (int x = 0 ... ) This is the preffered method.
    for (String staffMember : staffList) {
        // You now dont need to use .get() you can access the current variable using staffMember
        System.out.println(staffMember);

        // Do the work
        staffCheckBO.checkUser(staffMember);
    }
  }
}

旧 2 类

/**
 * Probably not really any need for this class but I'll assume further business logic may follow.
 */
public class StaffCheckBO {

// Again only create our DAO once...CREATING OBJECTS IS EXPENSIVE.
private StaffDAO staffDAO = new StaffDAO();

public void checkUser(String staffMember) throws Exception{

 boolean staffExists = staffDAO.checkStaffExists(staffMember);

     if(staffExists) {
         System.out.println(staffMember +" is not in database, doing new insert.");
         staffDAO.insertStaff(staffMember);
     } else {
         System.out.println(staffMember +" has been found in the database, updating user.");
         staffDAO.updateStaff(staffMember);
     }
   }
}

老3级

import java.sql.*;

/**
 * You will need to do some work to get this class to work fully and this is obviously     basic but its to give you an idea.
 */
public class StaffDAO {

public boolean checkStaffExists(String staffName) {
    boolean staffExists = false;

    try {
        String query = "SELECT * FROM STAFF_TABLE WHERE STAFF_NAME = ?";
        PreparedStatement preparedStatement = getDBConnection().prepareStatement(query);

        // Load your variables into the string in order to be safe against injection attacks.
        preparedStatement.setString(1, staffName);
        ResultSet resultSet = preparedStatement.executeQuery();

        // If a record has been found the staff member is in the database. This obviously doesn't account for multiple staff members
        if(resultSet.next()) {
            staffExists = true;
        }
    } catch (SQLException e) {
        System.out.println("SQL Exception in getStaff: " + e.getMessage());
    }

    return staffExists;
}

// Method names should be camel cased
public void updateStaff(String staffName) throws Exception {

    try {
        String query = "YOUR QUERY";
        PreparedStatement preparedStatement = getDBConnection().prepareStatement(query);

        // Load your variables into the string in order to be safe against injection attacks.
        preparedStatement.setString(1, staffName);
        ResultSet resultSet = preparedStatement.executeQuery();

    } catch (SQLException e) {
        System.out.println("SQL Exception in getStaff: " + e.getMessage());
    }

}

public void insertStaff(String staffName) throws Exception {

    try {
        String query = "YOUR QUERY";
        PreparedStatement preparedStatement = getDBConnection().prepareStatement(query);

        // Load your variables into the string in order to be safe against injection attacks.
        preparedStatement.setString(1, staffName);
        ResultSet resultSet = preparedStatement.executeQuery();

    } catch (SQLException e) {
        System.out.println("SQL Exception in getStaff: " + e.getMessage());
    }

}


/**
 * You need to abstract the connection logic away so you avoid code reuse.
 *
 * @return
 */
private Connection getDBConnection() {
    Connection connection = null;

    try {
        Class.forName("com.mysql.jdbc.Driver");

        connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/default", "root", "1234567");
    } catch (ClassNotFoundException e) {
        System.out.println("Could not find class. DB Connection could not be created: " + e.getMessage());
    } catch (SQLException e) {
        System.out.println("SQL Exception. " + e.getMessage());
    }

    return connection;
   }
}

关于java - 如何将字符串写入容器以在循环后使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21625732/

相关文章:

java - 异常和文件 I/O

java - 接口(interface)如何从 Object 类获取带有主体的方法?

MySQL : Get results from DB knowing that we don't want to get specific ids

php - 比较两个 PHP 报告之间的差异

linux - 写入远程文件 : When does write() really return?

java - LWJGL 在我的纹理上方添加线条

java - 来自 Servlet 的字符串,带有 XML CDATA 中的控制字符

php - mySQL使用表中的行快速查找第二个表中的多行

java - 用Java在文件中写入第x行

java - 如何读取 .txt 文件并每 8 个字符分割一次?