以前我在我的应用程序中使用了JDBC并且它运行得非常快,但是我已经修改它以使用Hibernate,这使得它太慢,特别是当它需要打开一个带有下拉框的页面时。与JDBC相比,打开这种页面需要更长的时间。
如果我尝试访问带有外键的表,则需要更长的时间。
我的服务器是GlassFish,我正在使用以下版本的hibernate。
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.1.10.Final</version>
<type>jar</type>
</dependency>
问题是为什么它与JDBC相比会变慢,我是否需要在每个session.beginTransaction()之前使用以下lin?
session = HibernateUtil.getSessionFactory().openSession();
以下面的一个为例,它有一个下拉框,需要在页面打开后填充。
HibernateUtil.java
package com.myproject.util;
import org.hibernate.HibernateException;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
public class HibernateUtil {
private static SessionFactory sessionFactory;
private static ServiceRegistry serviceRegistry;
private static SessionFactory configureSessionFactory() {
try {
System.out.println("1");
Configuration configuration = new Configuration();
configuration.configure();
serviceRegistry = new
ServiceRegistryBuilder()
.applySettings(configuration.getProperties())
.buildServiceRegistry();
System.out.println("2");
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
System.out.println("3");
return sessionFactory;
} catch (HibernateException e) {
System.out.append("** Exception in SessionFactory **");
e.printStackTrace();
}
return sessionFactory;
}
public static SessionFactory getSessionFactory() {
return configureSessionFactory();
}
}
MyClassModel.java
public class MyClassModel extends HibernateUtil {
private Session session;
public Map populatedropdownList() {
Map map = new HashMap();
session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
List<MyListResult> temp = null;
try{
temp = retrieveItems();
System.err.println("size:" + temp.size());
for(int i=0;i<temp.size();i++){
map.put(temp.get(i).getId(),temp.get(i).getName());
}
session.getTransaction().commit();
session.close();
return map;
}catch(Exception e){
e.printStackTrace();
}
return map;
}
private List <MyListResult> retrieveItems(){
Criteria criteria = session.createCriteria(MyTable.class, "MyTable");
ProjectionList pl = Projections.projectionList();
pl.add(Projections.property("MyTable.id").as("id"));
pl.add(Projections.property("MyTable.name").as("name"));
criteria.setProjection(pl);
criteria.setResultTransformer(new
AliasToBeanResultTransformer(MyListResult.class));
return criteria.list();
}
MyListResult.java
public class MyListResult implements Serializable {
private int id;
private String Name;
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;
}
}
hibernate.cfg.xml中
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">
com.mysql.jdbc.Driver
</property>
<property name="connection.url">
jdbc:mysql://localhost:3306/MyDatabase
</property>
<property name="connection.username">root</property>
<property name="connection.password"></property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">
org.hibernate.cache.NoCacheProvider
</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">update</property>
<mapping class="com.MyProject.MyTable" />
</session-factory>
</hibernate-configuration>
控制台如下
INFO: in myform
INFO: 1
INFO: HHH000043: Configuring from resource: /hibernate.cfg.xml
INFO: HHH000040: Configuration resource: /hibernate.cfg.xml
INFO: HHH000041: Configured SessionFactory: null
INFO: 2
INFO: HHH000402: Using Hibernate built-in connection pool (not for production use!)
INFO: HHH000115: Hibernate connection pool size: 1
INFO: HHH000006: Autocommit mode: false
INFO: HHH000401: using driver [com.mysql.jdbc.Driver] at URL
[jdbc:mysql://localhost:3306/MyDatabase]
INFO: HHH000046: Connection properties: {user=root, password=****}
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
INFO: HHH000399: Using default transaction strategy (direct JDBC transactions)
INFO: HHH000397: Using ASTQueryTranslatorFactory
INFO: HHH000228: Running hbm2ddl schema update
INFO: HHH000102: Fetching database metadata
INFO: HHH000396: Updating schema
INFO: HHH000261: Table found: MyDatabase.MyTable
INFO: HHH000037: Columns: [id, name, age, xx, yy]
INFO: HHH000126: Indexes: [primary]
INFO: HHH000232: Schema update complete
INFO: Hibernate: select this_.id as y0_, this_.name as y1_ from MyTable this_
SEVERE: size:4
答案 0 :(得分:1)
通常在应用程序中,每次需要会话时都不应构建会话工厂。这就是应用程序实际需要使用hibernate的东西。如果要手动管理会话,则编写HibernateUtil
使其成为单例。最初,在静态初始化程序块
private static final ThreadLocal<Session> threadLocal = new ThreadLocal<>();
private static SessionFactory sessionFactory;
static {
try {
sessionFactory = configureSessionFactory();
} catch (Exception e) {
System.err.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
}
private HibernateUtil() {
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
public static Session getSession() throws HibernateException {
Session session = threadLocal.get();
if (session == null || !session.isOpen()) {
if (sessionFactory == null) {
rebuildSessionFactory();
}
session = (sessionFactory != null) ? sessionFactory.openSession() : null;
threadLocal.set(session);
}
return session;
}
public static void rebuildSessionFactory() {
try {
sessionFactory = configureSessionFactory();
} catch (Exception e) {
System.err.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
}
public static void closeSession() throws HibernateException {
Session session = (Session) threadLocal.get();
threadLocal.set(null);
if (session != null) {
session.close();
}
}
认为您的代码足以添加到您的应用程序中。
答案 1 :(得分:0)
虽然我没有Hibernate的任何直接经验,但我使用的是NHibernate,它是以Java版本为模型的,所以这应该仍然是正确的......
构建SessionFactory
需要时间,尤其是如果我正在阅读正确的配置,那么在启动时,您需要检查模型与数据库之间的架构更改。
你应该做的是在启动时创建SessionFactory
一次(或者在第一次使用数据访问时,根据你想要支付设置Hibernate的成本的时间)并在生命周期中使用它你的应用。
我倾向于做的事情大致是这样的(粗糙的伪代码,因为我的Java生锈了):
Session getSession()
{
if(sessionFactory == null)
buildSessionFactory()
return sessionFactory.OpenSession()
}
(当然,这并未考虑任何可能的线程竞争条件)。希望看到相当大的性能提升。请记住,由于额外的映射层,ORM几乎从未像手工编写的SQL一样快,但它是性能和编码简易性之间的折衷。