postInstantiate buildSessionFactory慢/内存庞大的数据库

时间:2014-05-26 09:45:31

标签: java performance hibernate

拥有超过520个表的ERP数据库,EntityPersister的postInstanciate非常慢,耗费超过512M,这对于一个会话工厂而言非常缓慢。

1 个答案:

答案 0 :(得分:3)

我无法发布所有更改,但请注意以下内容:

1_ postInstanciate为所有实体和集合创建许多Entiy Loader(每个实体和每个集合的许多类型的加载器), 这个操作应该在demande上完成,实体或集合加载器应该在需要时创建,而不是在会话工厂的构建期间创建,即使你有500个实体,它也意味着用户将从所有实体加载数据。

    private Map LoaderMap = new LoaderMap();//instead Hashmap  
    class LoaderMap extends HashMap{
        @Override
        public Object get(Object key) {         
            Object obj = super.get(key);
            if (obj==null){
                boolean disableForUpdate = getSubclassTableSpan() > 1 &&
                        hasSubclasses() &&
                        !getFactory().getDialect().supportsOuterJoinForUpdate();

                switch (key.toString()) {
                case "NONE":
                    obj = createEntityLoader( LockMode.NONE );
                    break;
                case "READ":
                    obj = createEntityLoader( LockMode.READ );                  
                    if (disableForUpdate){
                        put(LockMode.UPGRADE, obj );
                        put(LockMode.UPGRADE_NOWAIT, obj );
                        put(LockMode.UPGRADE_SKIPLOCKED, obj );
                        put(LockMode.FORCE, obj );                                          
                        put(LockMode.PESSIMISTIC_READ, obj );
                        put(LockMode.PESSIMISTIC_WRITE, obj );
                        put(LockMode.PESSIMISTIC_FORCE_INCREMENT, obj );                        
                    }
                    break;
                case "UPGRADE":
                    if (disableForUpdate)
                        obj = get("READ");                       
                    else
                        obj = createEntityLoader( LockMode.UPGRADE );
                case "UPGRADE_NOWAIT":
                    if (disableForUpdate)
                        obj = get("READ");                       
                    else
                        obj = createEntityLoader( LockMode.UPGRADE_NOWAIT );
                case "UPGRADE_SKIPLOCKED":
                    if (disableForUpdate)
                        obj = get("READ");                       
                    else
                        obj = createEntityLoader( LockMode.UPGRADE_SKIPLOCKED );
                case "FORCE":
                    if (disableForUpdate)
                        obj = get("READ");                       
                    else
                        obj = createEntityLoader( LockMode.FORCE );
                case "PESSIMISTIC_READ":
                    if (disableForUpdate)
                        obj = get("READ");                       
                    else
                        obj = createEntityLoader( LockMode.PESSIMISTIC_READ );
                case "PESSIMISTIC_WRITE":
                    if (disableForUpdate)
                        obj = get("READ");                       
                    else
                        obj = createEntityLoader( LockMode.PESSIMISTIC_WRITE );
                case "PESSIMISTIC_FORCE_INCREMENT":
                    if (disableForUpdate)
                        obj = get("READ");                       
                    else
                        obj = createEntityLoader( LockMode.PESSIMISTIC_FORCE_INCREMENT );
                case "OPTIMISTIC":
                    obj = createEntityLoader( LockMode.READ );
                    break;
                case "OPTIMISTIC_FORCE_INCREMENT":
                    obj = createEntityLoader( LockMode.READ );
                    break;
                case "merge":
                    obj = new CascadeEntityLoader( AbstractEntityPersister.this, CascadingActions.MERGE, getFactory() );
                    break;                  
                case "refresh":
                    obj = new CascadeEntityLoader( AbstractEntityPersister.this, CascadingActions.REFRESH, getFactory() );
                    break;  
                default:
                    break;
                }
                put(key, obj);
            }
            return obj;
        }
    }
    //Relational based Persisters should be content with this implementation
    protected void createLoaders() {
        if (true)
            return;
....
       }

2_ DirectPropertyAccessor为buildGetter方法调用getDeclaredField两次,为buildSetter调用第二次,使用map是一个很好的优化。

public static final Map<Double, Field> tmp = new HashMap<Double, Field>();
    private static Field getField(Class root, Class clazz, String name) throws PropertyNotFoundException {
        if ( clazz==null || clazz==Object.class ) {
            throw new PropertyNotFoundException("field [" + name + "] not found on " + root.getName()); 
        }               
        double hash = name.hashCode() + clazz.hashCode()*1.1;
        Field field = tmp.get( hash );
        if (field==null)
        try {
            field = clazz.getDeclaredField(name);
            tmp.put( hash, field );
        }
        catch (NoSuchFieldException nsfe) {
            field = getField( root, clazz.getSuperclass(), name );
        }
        field.setAccessible(true);
        return field;
    }

对Ulrich Scholz的回应: 我将一个包含所有固定类的jar添加到项目中,在我的例子中,它在Tomcat上部署了Webapp应用程序,您只需要使用以下方法修复Jars的加载顺序:

<Context>
<Resources>
      <PreResources className="org.apache.catalina.webresources.FileResourceSet"
                base="${catalina.base}/webapps/AGIWERP/WEB-INF/lib/AAACLZ-1.0.jar"
                webAppMount="/WEB-INF/lib/AAACLZ-1.0.jar" />
</Resources>

</Context>

这意味着您的类应该在原始类之前加载