Play Framework + Java的批量操作

Play雖然很快捷,但也終究是存在不足之處,當批量操作時,只能用調用JPA去執行原生SQL,
本人這裏寫了批量修改與批量新增的操作這兩種操作。

網上查了很多,基本都是

//查到的第一種
 for (int i = 0; i < list.size(); i++) {
     em.persist(list.get(i));
     if (i % 100 == 0) {//一次一百條插入
         em.flush();
         em.clear();
     }
 }
 //查到的第二種
 for(DvdRateConfig rate : set) {  
    if(i%100==0) {  
         System.out.println(">>>>>>>>>>>>>>>>>>>>>>>flush");  
         JPA.em().flush();  
         JPA.em().clear();  
     }  
     rate.save();  
 }  

兩種方式都是調用flush更新到數據庫,無非就是以
insert in to table values(…)
insert in to table values(…)
.
.
.
這種方式每100條執行一次,但從代碼來看,以每一百條提交,雖然比單個提交效率提高很多,但也並不是我想要的結果(insert in to table values(…),(…)),所以還是需要JPA執行原生SQL,下面介紹批量新增與更新的批量操作:
1批量新增

/**
 * insert into test (admin_id, subject_id, update_time,status,name) values(...),(...);
 */
public static void testis() {
	List<Test1> list = new ArrayList<Test1>();
	for (int i = 0; i < 10; i++) {
		Test1 t = new Test1(); 
		t.admin_id = 1L;
		t.subject_id = 1L;
		t.status = 2;
		t.update_time = new Date();
		t.name = "'測試增加"+(i+1)+"號'";
		list.add(t);
	}
	
	StringBuffer insertSql = new StringBuffer();
	insertSql.append("insert into test (admin_id, subject_id, update_time,status,name) values");
	for (int i = 0; i < list.size(); i++) {
		
		insertSql.append("(");
		insertSql.append(list.get(i).admin_id+",");
		insertSql.append(list.get(i).subject_id+",");
		insertSql.append("str_to_date('"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(list.get(i).update_time).toString()+"','%Y-%m-%d %H:%i:%s'),");
		insertSql.append(list.get(i).status+",");
		insertSql.append(list.get(i).name); 
		insertSql.append(")");
		if(i!=list.size()-1){
			insertSql.append(",");
		}
	}
	Query createNativeQuery = JPA.em().createNativeQuery(insertSql.toString()); 
	int executeUpdate = createNativeQuery.executeUpdate();
	System.out.println(executeUpdate);//影響條數
	
}

2批量修改

/**
 * 
 * UPDATE test
 *     SET name = CASE id 
 *         WHEN 426 THEN '測試修改426'
 * 		   WHEN 427 THEN '測試修改427'
 *     END
 * WHERE id IN (426,427)
 */
public static void testus() {
	List<Test1> list = new ArrayList<Test1>();
	for (int i = 0; i < 10; i++) {
		Test1 t = new Test1(); 
		t.id = 456+Long.parseLong(i+"");
		t.admin_id = 2L;
		t.subject_id = 3L;
		t.status = 2;
		t.update_time = new Date();
		t.name = "'測試修改"+(i+100)+"號'";
		list.add(t);
	}
	
	String updateSql = "update test set admin_id = case id adminIdWhenThen end, subject_id = case id subjectIdWhenThen end, name =  case id nameWhenThen end where id in (whereIds)";
	StringBuffer adminIdWhenThen = new StringBuffer();
	StringBuffer subjectIdWhenThen = new StringBuffer();
	StringBuffer nameWhenThen = new StringBuffer();
	StringBuffer whereIds = new StringBuffer();
			
	for (int i = 0; i < list.size(); i++) {
		adminIdWhenThen.append(" when "+list.get(i).id+" then "+list.get(i).admin_id);
		subjectIdWhenThen.append(" when "+list.get(i).id+" then "+list.get(i).subject_id);
		nameWhenThen.append(" when "+list.get(i).id+" then "+list.get(i).name+"");
		whereIds.append(list.get(i).id);
		if(i != list.size()-1){
			whereIds.append(",");
		}
	}
	updateSql = updateSql.replace("adminIdWhenThen", adminIdWhenThen.toString()).replace("subjectIdWhenThen", subjectIdWhenThen.toString())
									  .replace("nameWhenThen", nameWhenThen.toString()).replace("whereIds", whereIds.toString());
	
	Query createNativeQuery = JPA.em().createNativeQuery(updateSql.toString()); 
	int executeUpdate = createNativeQuery.executeUpdate();
	System.out.println(executeUpdate);
}

需要特別注意,這裏有幾處坑:
1、createNativeQuery是執行原生SQL的方法,createQuery是執行HQL語句的方法。
2、拼接SQL時,屬性爲字符時,應該用’'或""包住,完全按照SQL規範,例:‘測試’
3、同上,屬性爲時間類型時,需要SimpleDateFormat格式化一下,再用STR_TO_DATE(str,format)轉換一下,特別需要注意,這裏不能用雙引號包住,如果是"2018-11-20 10:10:10"這種格式會報類型錯誤,因爲數據庫是dateTime類型,所以需要轉換。
3.1、附上mysql時間類型轉換:
STR_TO_DATE(str,format)–字符轉時間
DATE_FORMAT(date,format)–時間轉字符
%Y:代表4位的年份
%y:代表2爲的年份
%m:代表月, 格式爲
%d:代表月份中的天數
%H:代表小時,格式爲(00……23)
%h: 代表小時,格式爲(01……12)
%i: 代表分鐘
%S:代表 秒
4、如果數據量大時,需要分批操作,可以調用以下方法來手動批量提交
JPA.em().getTransaction().begin();
JPA.em().getTransaction().commit();
JPA.em().getTransaction().rollback();

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章