Browse Source

Model、Db 新增 each 方法

James 5 years ago
parent
commit
b113818b5b

+ 19 - 0
src/main/java/com/jfinal/plugin/activerecord/Db.java

@@ -21,6 +21,7 @@ import java.sql.SQLException;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.Future;
+import java.util.function.Function;
 import com.jfinal.kit.SyncWriteMap;
 
 /**
@@ -731,6 +732,24 @@ public class Db {
 	// ---------
 	
 	/**
+	 * 迭代处理每一个查询出来的 Record 对象
+	 * <pre>
+	 * 例子:
+	 * Db.each(record -> {
+	 *    // 处理 record 的代码在此
+	 *    
+	 *    // 返回 true 继续循环处理下一条数据,返回 false 立即终止循环
+	 *    return true;
+	 * }, sql, paras);
+	 * </pre>
+	 */
+	public void each(Function<Record, Boolean> func, String sql, Object... paras) {
+		MAIN.each(func, sql, paras);
+	}
+	
+	// ---------
+	
+	/**
 	 * 使用 sql 模板进行查询,可以省去 Db.getSqlPara(...) 调用
 	 * 
 	 * <pre>

+ 34 - 0
src/main/java/com/jfinal/plugin/activerecord/DbPro.java

@@ -30,6 +30,7 @@ import java.util.Map.Entry;
 import java.util.Set;
 import java.util.concurrent.Future;
 import java.util.concurrent.FutureTask;
+import java.util.function.Function;
 import com.jfinal.kit.LogKit;
 import com.jfinal.kit.StrKit;
 import com.jfinal.plugin.activerecord.cache.ICache;
@@ -1367,6 +1368,39 @@ public class DbPro {
 	
 	// ---------
 	
+	/**
+	 * 迭代处理每一个查询出来的 Record 对象
+	 * <pre>
+	 * 例子:
+	 * Db.each(record -> {
+	 *    // 处理 record 的代码在此
+	 *    
+	 *    // 返回 true 继续循环处理下一条数据,返回 false 立即终止循环
+	 *    return true;
+	 * }, sql, paras);
+	 * </pre>
+	 */
+	public void each(Function<Record, Boolean> func, String sql, Object... paras) {
+		Connection conn = null;
+		try {
+			conn = config.getConnection();
+			
+			try (PreparedStatement pst = conn.prepareStatement(sql)) {
+				config.dialect.fillStatement(pst, paras);
+				ResultSet rs = pst.executeQuery();
+				config.dialect.eachRecord(config, rs, func);
+				DbKit.close(rs);
+			}
+			
+		} catch (Exception e) {
+			throw new ActiveRecordException(e);
+		} finally {
+			config.close(conn);
+		}
+	}
+	
+	// ---------
+	
 	public DbTemplate template(String key, Map data) {
 		return new DbTemplate(this, key, data);
 	}

+ 35 - 0
src/main/java/com/jfinal/plugin/activerecord/Model.java

@@ -28,6 +28,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.Map.Entry;
+import java.util.function.Function;
 import com.jfinal.plugin.activerecord.cache.ICache;
 import static com.jfinal.plugin.activerecord.DbKit.NULL_PARA_ARRAY;
 
@@ -1092,6 +1093,40 @@ public abstract class Model<M extends Model> implements Serializable {
 	// ---------
 	
 	/**
+	 * 迭代处理每一个查询出来的 Model 对象
+	 * <pre>
+	 * 例子:
+	 * Db.each(model -> {
+	 *    // 处理 model 的代码在此
+	 *    
+	 *    // 返回 true 继续循环处理下一条数据,返回 false 立即终止循环
+	 *    return true;
+	 * }, sql, paras);
+	 * </pre>
+	 */
+	public void each(Function<Model, Boolean> func, String sql, Object... paras) {
+		Config config = _getConfig();
+		Connection conn = null;
+		try {
+			conn = config.getConnection();
+			
+			try (PreparedStatement pst = conn.prepareStatement(sql)) {
+				config.dialect.fillStatement(pst, paras);
+				ResultSet rs = pst.executeQuery();
+				config.dialect.eachModel(rs, _getUsefulClass(), func);
+				DbKit.close(rs);
+			}
+			
+		} catch (Exception e) {
+			throw new ActiveRecordException(e);
+		} finally {
+			config.close(conn);
+		}
+	}
+	
+	// ---------
+	
+	/**
 	 * 使用 sql 模板进行查询,可以省去 getSqlPara(...) 调用
 	 * 
 	 * <pre>

+ 15 - 2
src/main/java/com/jfinal/plugin/activerecord/ModelBuilder.java

@@ -28,6 +28,7 @@ import java.sql.Types;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Function;
 
 /**
  * ModelBuilder.
@@ -36,8 +37,13 @@ public class ModelBuilder {
 	
 	public static final ModelBuilder me = new ModelBuilder();
 	
-	@SuppressWarnings({"rawtypes", "unchecked"})
+	@SuppressWarnings({"rawtypes"})
 	public <T> List<T> build(ResultSet rs, Class<? extends Model> modelClass) throws SQLException, ReflectiveOperationException {
+		return build(rs, modelClass, null);
+	}
+	
+	@SuppressWarnings({"rawtypes", "unchecked"})
+	public <T> List<T> build(ResultSet rs, Class<? extends Model> modelClass, Function<Model, Boolean> func) throws SQLException, ReflectiveOperationException {
 		List<T> result = new ArrayList<T>();
 		ResultSetMetaData rsmd = rs.getMetaData();
 		int columnCount = rsmd.getColumnCount();
@@ -65,7 +71,14 @@ public class ModelBuilder {
 				
 				attrs.put(labelNames[i], value);
 			}
-			result.add((T)ar);
+			
+			if (func == null) {
+				result.add((T)ar);
+			} else {
+				if ( ! func.apply((Model)ar) ) {
+					break ;
+				}
+			}
 		}
 		return result;
 	}

+ 14 - 2
src/main/java/com/jfinal/plugin/activerecord/RecordBuilder.java

@@ -23,6 +23,7 @@ import java.sql.Types;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Function;
 
 /**
  * RecordBuilder.
@@ -31,8 +32,12 @@ public class RecordBuilder {
 	
 	public static final RecordBuilder me = new RecordBuilder();
 	
-	@SuppressWarnings("unchecked")
 	public List<Record> build(Config config, ResultSet rs) throws SQLException {
+		return build(config, rs, null);
+	}
+	
+	@SuppressWarnings("unchecked")
+	public List<Record> build(Config config, ResultSet rs, Function<Record, Boolean> func) throws SQLException {
 		List<Record> result = new ArrayList<Record>();
 		ResultSetMetaData rsmd = rs.getMetaData();
 		int columnCount = rsmd.getColumnCount();
@@ -61,7 +66,14 @@ public class RecordBuilder {
 				
 				columns.put(labelNames[i], value);
 			}
-			result.add(record);
+			
+			if (func == null) {
+				result.add(record);
+			} else {
+				if ( ! func.apply(record) ) {
+					break ;
+				}
+			}
 		}
 		return result;
 	}

+ 10 - 0
src/main/java/com/jfinal/plugin/activerecord/dialect/Dialect.java

@@ -24,6 +24,7 @@ import java.sql.SQLException;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.Function;
 import java.util.regex.Pattern;
 import com.jfinal.plugin.activerecord.Config;
 import com.jfinal.plugin.activerecord.Model;
@@ -134,10 +135,19 @@ public abstract class Dialect {
 		return modelBuilder.build(rs, modelClass);
 	}
 	
+	@SuppressWarnings("rawtypes")
+	public void eachModel(ResultSet rs, Class<? extends Model> modelClass, Function<Model, Boolean> func) throws SQLException, ReflectiveOperationException {
+		modelBuilder.build(rs, modelClass, func);
+	}
+	
 	public List<Record> buildRecordList(Config config, ResultSet rs) throws SQLException {
 		return recordBuilder.build(config, rs);
 	}
 	
+	public void eachRecord(Config config, ResultSet rs, Function<Record, Boolean> func) throws SQLException {
+		recordBuilder.build(config, rs, func);
+	}
+	
 	/**
 	 * 用于获取 Model.save() 以后自动生成的主键值,可通过覆盖此方法实现更精细的控制
 	 * 目前只有 PostgreSqlDialect,覆盖过此方法