いろいろベンチ(3)
いろいろリンクされてるようなので,恥を忍んでコードを公開します(とゆうても断片だけど).
#おかしなところがあったら,ご指摘願いまーす.
まず,INSERT.以下のコードをそれぞれ1000回繰り返してかかった時間を計測.
===JDBC=== private void createCats(Connection con, int id) throws Exception { PreparedStatement st = con.prepareStatement("INSERT INTO CAT VALUES(?, ?, ?, ?)"); st.setString(1, ""+id); st.setString(2, "princess"); st.setString(3, "F"); st.setFloat(4, id); st.executeUpdate(); st.close(); } ===Hibernate=== private void createCats(Session session, int id) throws Exception { Cat princess = new Cat(); princess.setName("princess"); princess.setSex('F'); princess.setWeight(id); session.save(princess); } ===Torque=== private void createCats(Connection con, int id) throws Exception { Cat princess = new Cat(); princess.setCatId(""+id); princess.setName("princess"); princess.setSex("F"); princess.setWeight(id); princess.save(con); } ===DbUtils=== private void createCats(Connection con, int id) throws Exception { QueryRunner qr = new QueryRunner(); qr.update(con, "INSERT INTO CAT VALUES(?, ?, ?, ?)", new Object[] { ""+id, "princess", "F", new Float(id) }); }
んで,1000レコードできたんで,それを1000回SELECTする(以下のコードを1000回繰り返す).
===JDBC=== private List selectAllCats(Connection con) throws Exception { List list = new ArrayList(); PreparedStatement st = con.prepareStatement("SELECT * FROM CAT"); ResultSet rs = st.executeQuery(); while(rs.next()) { Cat cat = new Cat(); cat.setId(rs.getString(1)); cat.setName(rs.getString(2)); cat.setSex(rs.getString(3).charAt(0)); cat.setWeight(rs.getFloat(4)); list.add(cat); } rs.close(); st.close(); return list; } ===Hibernate=== private List selectAllCats(Session session) throws Exception { List list = new ArrayList(); Query query = session.createQuery("select cat from Cat as cat"); for (Iterator it = query.iterate(); it.hasNext();) { Cat cat = (Cat) it.next(); list.add(cat); } return list; } ===Torque=== private List selectAllCats(Connection con) throws Exception { return CatPeer.doSelect(new Criteria(), con); } ===DbUtils=== private List selectAllCats(Connection con) throws Exception { ResultSetHandler h = new BeanListHandler(Cat.class); QueryRunner run = new QueryRunner(); List list = (List) run.query(con, "SELECT * FROM CAT", h); return list; }
SELECTで取得した1000個のオブジェクトを以下のように1つ1つUPDATEする.
===JDBC=== private void updateCats(Connection con, List list) throws Exception { float f = 0; for (Iterator it = list.iterator(); it.hasNext(); ) { Cat cat = (Cat)it.next(); PreparedStatement st; st = con.prepareStatement("UPDATE CAT SET NAME=?, sex=?, weight=? WHERE cat_id=?"); st.setString(1, cat.getName().toUpperCase()); st.setString(2, "M"); st.setFloat(3, cat.getWeight() + f++); st.setString(4, cat.getId()); st.executeUpdate(); st.close(); } } ===Hibernate=== private void updateCats(Session session, List list) throws Exception { float f = 0.0f; for (Iterator it = list.iterator(); it.hasNext(); ) { Cat cat = (Cat)it.next(); cat.setName(cat.getName().toUpperCase()); cat.setSex('M'); cat.setWeight(cat.getWeight() + f++); session.update(cat); } } ===Torque=== private void updateCats(Connection con, List list) throws Exception { for (Iterator it = list.iterator(); it.hasNext(); ) { Cat cat = (Cat)it.next(); cat.setName(cat.getName().toUpperCase()); cat.setSex("M"); cat.setWeight(cat.getWeight() + 1.0f); cat.save(con); } } ===DbUtils=== private void updateCats(Connection con, List list) throws Exception { float f = 0; for (Iterator it = list.iterator(); it.hasNext(); ) { Cat cat = (Cat)it.next(); QueryRunner run = new QueryRunner(); run.update(con, "UPDATE CAT SET NAME=?, sex=?, weight=? WHERE cat_id=?", new Object[] { cat.getName().toUpperCase(), "M", new Float(cat.getWeight() + f++), cat.getId() }); } }
で最後は,この1000個のオブジェクトを,以下のコードで1つ1つDELETEして,おしまい.
===JDBC=== private void deleteCats(Connection con, List list) throws Exception { for (Iterator it = list.iterator(); it.hasNext();) { Cat cat = (Cat) it.next(); PreparedStatement st = con.prepareStatement("DELETE FROM CAT WHERE cat_id=?"); st.setString(1, cat.getId()); st.executeUpdate(); st.close(); } } ===Hibernate=== private void deleteCats(Session session, List list) throws Exception { for (Iterator it = list.iterator(); it.hasNext();) { Cat cat = (Cat) it.next(); session.delete(cat); } } ===Torque=== private void deleteCats(Connection con, List list) throws Exception { for (Iterator it = list.iterator(); it.hasNext();) { Cat cat = (Cat) it.next(); CatPeer.doDelete(cat, con); } } ===DbUtils=== private void deleteCats(Connection con, List list) throws Exception { for (Iterator it = list.iterator(); it.hasNext();) { Cat cat = (Cat)it.next(); QueryRunner run = new QueryRunner(); run.update(con, "DELETE FROM CAT WHERE cat_id=?", cat.getId()); } }
トランザクションは,INSERT, SELECT, UPDATE, DELETEごとで完結.
テストに使ったのは,HibernateサンプルにあるCatテーブル.Hibernateは,ID生成にuuid.hexを指定してるけど,他はテキトウ.
なんで,ちょっとHibernate不利な設定だったのかもしれない.
あとTorqueの生成方法はよくわかんないんで,Torque-genにあったのを見よう見まねで書き換えて生成.
Hibernateのオプションは,いじってません.せいぜい,
hibernate.cglib.use_reflection_optimizer
をON/OFFしてみたくらいです.
んで,使ったバージョンは,
- Hibernate2.1
- Torque3.1
- DbUtils1.0
でした.
ps.
追いかけては無いんですが,P6Spyでのぞいたところ,なんでかHibernateはINSERT, UPDATE, DELETEは6〜7回しかログに出てなかったんだよね.
#SELECTはちゃんと1000回ログ出てんのに.
ps2.
あと,これも追いかけてないんですが...
#ちゃんとギモンは追求しようよ>おれ.
TorqueやHibernateは,更新するオブジェクトが取得したときと何も変わってないと,UPDATE文を実行したないみたいですが,これは事実なんでしょか?