一尘不染

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

hibernate

拥有一个拥有520多个表的ERP数据库,EntityPersister的postInstanciate速度非常慢,并且消耗的512M以上(仅对于一个会话Factory而言是很大的),应用程序也变得非常慢。


阅读 315

收藏
2020-06-20

共1个答案

一尘不染

我无法发布所有更改,但是这里有一些想法:

1_
postInstanciate为所有实体和集合创建许多Entiy加载器(每个实体和每个集合的加载器类型很多),此操作应按需执行,应在需要时创建实体或集合加载器,而不是在会话工厂构建期间,即使您有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,在我的情况下,其Webapp应用程序部署在Tomcat上,您需要使用以下命令修复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>

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

2020-06-20