我有一个应用程序,它创建多个查询(更新或插入),然后执行每个查询。
整个代码工作正常,但我发现在此过程中我的服务器 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
最受欢迎)。
例如,如果我想存储查询字符串以供以后使用,我会...
- 使用 StringBuilder 构造字符串。
- 将字符串(通过调用 .toString() 放入 HashMap
- 从 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/