本文介绍了postSampletiate buildSessionFactory缓慢/内存庞大的数据库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

拥有超过520个表的ERP数据库后,EntityPersister的postInstanciate非常慢,消耗超过512M,这对于只有一个会话Factory来说非常重要,应用程序变得非常慢。

解决方案

我无法发布所有更改,但这里的想法是:
$ b $ 1_ postInstanciate create many Entiy所有实体和集合的装载器(每个实体和每个集合的许多类型的装载器),
这个操作应该在demande上完成,实体或集合装载器应该在需要时创建,而不是在会话工厂的构建期间创建,即使您有500个实体,它也意味着用户将加载所有数据。

  private Map LoaderMap = new LoaderMap() ; //改为HashMap 
class LoaderMap扩展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()){
caseNONE:
obj = createEntityLoader(LockMode.NONE);
休息;
caseREAD:
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;
caseUPGRADE:
if(disableForUpdate)
obj = get(READ);
else
obj = createEntityLoader(LockMode.UPGRADE);
caseUPGRADE_NOWAIT:
if(disableForUpdate)
obj = get(READ);
else
obj = createEntityLoader(LockMode.UPGRADE_NOWAIT);
caseUPGRADE_SKIPLOCKED:
if(disableForUpdate)
obj = get(READ);
else
obj = createEntityLoader(LockMode.UPGRADE_SKIPLOCKED);
caseFORCE:
if(disableForUpdate)
obj = get(READ);
else
obj = createEntityLoader(LockMode.FORCE);
casePESSIMISTIC_READ:
if(disableForUpdate)
obj = get(READ);
else
obj = createEntityLoader(LockMode.PESSIMISTIC_READ);
casePESSIMISTIC_WRITE:
if(disableForUpdate)
obj = get(READ);
else
obj = createEntityLoader(LockMode.PESSIMISTIC_WRITE);
casePESSIMISTIC_FORCE_INCREMENT:
if(disableForUpdate)
obj = get(READ);
else
obj = createEntityLoader(LockMode.PESSIMISTIC_FORCE_INCREMENT);
caseOPTIMISTIC:
obj = createEntityLoader(LockMode.READ);
休息;
caseOPTIMISTIC_FORCE_INCREMENT:
obj = createEntityLoader(LockMode.READ);
休息;
casemerge:
obj = new CascadeEntityLoader(AbstractEntityPersister.this,CascadingActions.MERGE,getFactory());
休息;
caserefresh:
obj = new CascadeEntityLoader(AbstractEntityPersister.this,CascadingActions.REFRESH,getFactory());
休息;
默认值:
break;
}
put(key,obj);
}
return obj;


//基于关系的Persister应该满足于这个实现
protected void createLoaders(){
if(true)
return;
....
}

2_ DirectPropertyAccessor正在调用getDeclaredField两次buildGetter方法和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(在+ root.getName())上找不到字段[+ name +];
}
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);
返回字段;
}

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

 <语境GT; 
<资源>
< PreResources className =org.apache.catalina.webresources.FileResourceSet
ase =$ {catalina.base} /webapps/AGIWERP/WEB-INF/lib/AAACLZ-1.0.jar
webAppMount =/ WEB-INF / lib / AAACLZ-1.0.jar/>
< /资源>

< / Context>

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

Having an ERP database with more than 520 tables, the postInstanciate of EntityPersister is very slow and its consuming more than 512M which is to much for only one session Factory, the application become very slow.

解决方案

I can't post all changes, but here the ideas :

1_ postInstanciate create many Entiy Loaders for all entities and collections (many type of loader for each entity and each collection), this operation should be done on demande, entity or collection loader should be created when its needed, not during the build of session factory, even if you have 500 entities it dosent mean that the user will load data from all.

    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 is calling getDeclaredField twice once for the buildGetter Method and the second for buildSetter, using map is a good optimization.

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;
    }

Response to Ulrich Scholz:I add a jar containning all fixed Classes to the project, in my case its Webapp application deployed on Tomcat, all you need is to fix the loading order of the Jars using :

<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>

This mean your classes should be loaded before the original ones

这篇关于postSampletiate buildSessionFactory缓慢/内存庞大的数据库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-27 18:22