今天原打算研究一下Hibernate 1+N问题,却发现了一个Really Amazing的效率问题,问题如下,希望大牛可以解释一下:
1、简单描述一下测试中表结构(我用Mysql数据库),表结构如下图
表名为Corporation,三个字段id、name、type,对应Mysql中表结构截图:
2、如下代码,简单调运JDBC测试插入10000条数据花费时间
public class DB {
public static Connection getConn() {
Connection conn = null;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/hibernate?user=root&password=root");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
public static Statement getStmt(Connection conn) {
Statement stmt = null;
try {
if(conn != null) {
stmt = conn.createStatement();
}
} catch (SQLException e) {
e.printStackTrace();
}
return stmt;
}
public static void main(String[] args) throws SQLException {
Statement stmt = getStmt(getConn());
Date start = new Date();
for(int i = 0 ; i < 10000 ; i ++) {
String sql = "insert into corporation(name,type) value('Tibco','IT')";
stmt.executeUpdate(sql);
}
System.out.println("Total spent " + (new Date().getTime() - start.getTime()));
}
}
运行时间如下
Total spent 249531
这个时间我觉得是比较合理的执行一条SQL花费25毫秒左右,之前有关效率方面的测试和这个结果差不多
3. 下面给出Hibernate中测试时间的代码,先给出Hibernate配置代码
3.1 Corporation对应的Annotation配置类
@Entity
public class Corporation {
private int id;
private String name;
private String type;
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
3.2 hibernate.cfg.xml配置信息
<hibernate-configuration> <session-factory> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url">jdbc:mysql://localhost/hibernate</property> <property name="connection.username">root</property> <property name="connection.password">root</property> <property name="connection.pool_size">1</property> <property name="current_session_context_class">thread</property> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property> <property name="show_sql">true</property> <property name="format_sql">true</property> <property name="hbm2ddl.auto">update</property> <mapping class="com.kylin.test.Corporation"/> </session-factory> </hibernate-configuration>
3.3给出测试代码
package com.kylin.test;
import java.util.Date;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
public class AllTest {
private static SessionFactory sessionFactory;
@BeforeClass
public static void beforeClass(){
sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
}
@AfterClass
public static void afterClass() {
sessionFactory.close();
}
@Test
public void testExportTable() {
new SchemaExport(new AnnotationConfiguration().configure()).create(true, true);
}
@Test
public void saveCorporation() {
Date start = new Date();
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
for(int i = 0 ; i < 10000 ; i ++) {
Corporation c = new Corporation();
c.setName("Tibco");
c.setType("IT");
session.save(c);
}
session.getTransaction().commit();
System.out.println("Total spent " + (new Date().getTime() - start.getTime()));
}
}
如上saveCorporation()方法就是Hibernate想数据库中插入10000条数据的部分,这个结果确实令我吃惊,如下
Total spent 8781
我测试了多次这个时间都是8700毫秒左右,所以这个时间应该准确。
249531 / 8781 = 28.41,28倍,的确是28倍
4、分析一下
之前比较过Cassandra(分布式数据库)与Mysql的存储效率差别时发现关系数据库存储的SQL操作效率相当低,而Hibernate解决的是可以面向对象的操作关系数据库,所以我个人一直以为,Hibernate操作数据库的效率一定更低,但结果却恰恰相反,而且与我的之前的理解相差很大,所以我可以肯定的是Hibernate在数据操作效率上也有一定的技巧,大家谁知道可以说说。
PS。。本来还想再分析分析,但是周末了,不想再多呆在公司……