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();