2014-01-16 2 views
3

Я использую EclipseLink для моего проекта. Я расширяю XMLMetadataSource (чтобы предоставить пользовательский загрузчик классов), поскольку сущности, которые я сохраняю, созданы во время выполнения. И он работает нормально.Ключи сопоставления сущности Eclipselink

Я получаю «неизвестный тип сущности», когда делаю следующий.

  • Создать объект

  • Создать отображение

  • создать объект менеджера фабрики, обеспечивают пользовательский загрузчик классов

  • создать диспетчер сущностей и сохраняются. - ЭТО РАБОТАЕТ ОК.

  • теперь выпадают сущность, и падение с загрузчиком класса

  • создать ту же сущность,

  • создать отображение снова (конечно, это выглядит так же)

  • попытаться обновить лица менеджер завода с новые свойства (загрузчик нового класса, файл сопоставления)

  • попытаться сохранить - жалуется «неизвестный тип»

Любая идея, если EL кэширует XML-сопоставления. Я попытался снова заново создать завод, но с той же ошибкой.

Я пробовал MySQL и Derby. с «drop-and-create-tables» и «create-or-extend-tables».

такой же результат.

ответ

0

Да, загрузка единицы нагрузки выполняется только один раз. Если вы используете XMLMetadataSource изменить сопоставление, вы должны сообщить фабрике, чтобы обновить ее отображение, используя refreshMetadata() на EMF, как описано здесь: http://wiki.eclipse.org/EclipseLink/DesignDocs/340192#Refresh

После этого, следующее EntityManagers полученного будут использовать новые отображения, в то время как существующие ЭМ будут по-прежнему использовать старые сопоставления.

+0

Спасибо за ваш ответ. На самом деле я делаю обновление – PGK

+0

Спасибо за ваш ответ. На самом деле я делаю обновление, используя следующее. MyXMLMetadataSourceInstance.setClassLoader (myclassloader); props.put (PersistenceUnitProperties.METADATA_SOURCE, MyXMLMetadataSourceInstance); JpaHelper.getEntityManagerFactory (emfactory) .refreshMetadata (реквизит); – PGK

+0

И я заметил, что дескрипторы в 'org.eclipse.persistence.internal.sessions.AbstractSession' /** PERF: дескрипторы кеша из проекта. */ переходные защищенные карты дескрипторы ; не может вернуть объект дескриптора класса во второй раз (удаление созданного объекта времени выполнения, воссоздание снова с тем же именем) Я подозреваю, что он кэширован, а при обновлении он не очищается. В любом случае, как очистить весь кеш. Я кратко рассмотрел реализацию интерфейса ProjectCache, но похоже, что создание объекта Project является сложной задачей. – PGK

1

Его не ошибка в говорят в EL. Но проблема заключается в том, что EL «не создает или не воссоздает» class -> class_descriptor 'map (внутренняя карта, которая содержит объект класса каждого описания сущности и сущностей) .Я обнаружил это случайно. Для тех, кого это интересует, вот пример кода это может помочь.

public class Test1 { 
public Test1(String pu, Map<String, Object> props) { 
    pu_name = pu;   
    properties = new HashMap<String, Object>(); 
    properties.putAll(props); 
    loader = new MyClassLoader(); 
} 
public void initialization() {     
    mms = new WAMetadataSource(); 
    properties.put(PersistenceUnitProperties.METADATA_SOURCE, mms); 
    properties.put(PersistenceUnitProperties.CLASSLOADER,loader); 

    if(emf == null || !emf.isOpen()) { 
     synchronized(Test1.class) { 
      if (emf == null || !emf.isOpen()) { 
       emf = Persistence.createEntityManagerFactory(pu_name, properties);      
      } 
     }    
    } else { 
       JpaHelper.getEntityManagerFactory(emf).refreshMetadata(properties);   
    } 
    System.out.println("======> refreshed. emf.hascode : " + emf.hashCode() + ", loader.h : " + loader.hashCode()); 
} public EntityManager getEntityManager(Map<String, Object> props) { 
    if (em == null) { 
     em = emf.createEntityManager(props); 
    } 

    return em; 
} public void persist(Object obj) { 
    try { 
     getEntityManager(properties); 
     System.out.println("===> em.hascode =" + em.hashCode() +", " + JpaHelper.getEntityManager(em).getProperties().get(PersistenceUnitProperties.CLASSLOADER).hashCode()); 
     em.clear(); 
     em.getTransaction().begin(); 
     em.persist(obj); 
     em.getTransaction().commit(); 
    } finally { 
    }  
}public Object getRuntimeEntityObject(int ii) { 
     Object obj=null; 
     Class clazz = loader.loadClass("com.xxx.sample.entity.runtime.User"); 
     if(ii == 1){ 
      obj = clazz.getConstructor(String.class).newInstance("Jai Ramjiki-1");     
     } else { 
      obj = clazz.getConstructor(String.class).newInstance("Jai Ramjiki-2"); 
     } 
     obj = clazz.cast(obj); 
     return obj; 
}public static void main(String[] args) { 
    Map<String, Object> props = new HashMap<String, Object>(); 
    props.put(PersistenceUnitProperties.JDBC_DRIVER, "com.mysql.jdbc.Driver"); 
    props.put(PersistenceUnitProperties.JDBC_URL, "jdbc:mysql://localhost:3306/test"); 
    props.put(PersistenceUnitProperties.JDBC_USER, "root"); 
    props.put(PersistenceUnitProperties.JDBC_PASSWORD, "root"); 
    props.put(PersistenceUnitProperties.DDL_GENERATION, "create-or-extend-tables"); 

    Test1 t1 = new Test1("mysql", props);   
    Object obj1 = t1.getRuntimeEntityObject(1);  
    System.out.println(" ****> obj1 = " + obj1 + ", classloader hashcode : " + obj1.getClass().getClassLoader().hashCode()); 
    t1.initialization(); 
    t1.persist(obj1); 
    System.out.println("Class 1 : " + obj1.getClass().hashCode() + ", obj1 : " + obj1); 
    t1.close(); 

    // now drop the previous class loader and rerun same. 

    Test1 t2 = new Test1("mysql", props); 
    Object obj2 = t2.getRuntimeEntityObject(2); 
    System.out.println(" ****> obj2 = " + obj2 + ", classloader hashcode : " + obj2.getClass().getClassLoader().hashCode()); 
    t2.initialization(); 
    t2.persist(obj2); 
    t2.close(); 


    Object obj3 = t1.getRuntimeEntityObject(1); 
    System.out.println(" ****> obj3 = " + obj3 + ", classloader hashcode : " + obj3.getClass().getClassLoader().hashCode()); 
    t1.persist(obj3); 


} 

И продлить XMLMetadatSource

@Override 
public XMLEntityMappings getEntityMappings(Map<String, Object> properties, ClassLoader classLoader, SessionLog log) { 
    properties.put(PersistenceUnitProperties.METADATA_SOURCE_XML_FILE, "eclipselink-orm-user.xml"); 
    properties.put(PersistenceUnitProperties.VALIDATOR_FACTORY, null); 
    return super.getEntityMappings(properties, classLoader, log); 
} 

И создать класс выполнения, используя Javassist в вашем CustomClassloader, который проходит ClassLoader

public void createRuntimeClass(String className) throws Exception {   
    CtClass bclass = pool.makeClass(className); 
    bclass.addConstructor(CtNewConstructor.defaultConstructor(bclass));   
    Map<String, String> fields = new HashMap<String, String>(); 
    addFields(fields); 
    int noOfFields = fields.size(); 
    CtClass[] fclasses = new CtClass[noOfFields]; 

    int ii=0; 
    for (Entry<String, String> field : fields.entrySet()) { 
     String fieldName = field.getKey(); 
     String fieldType = field.getValue(); 
     //.. code to add field 
     bclass.addField(bfield);    
     //add getter method. 
     // add getter and setters 
    }   
    CtConstructor userConstructor = CtNewConstructor.make(constructorSource, bclass); 
    bclass.addConstructor(userConstructor); 
    byte bytes [] = bclass.toBytecode();   
    Class cls = bclass.toClass(this, null); 
    loadedClasses.put(className, cls); 
    loadClassBytes.put(className, bytes);  
} 

и Процентовка loadClass и getResourceAsStream методы.

public Class<?> loadClass(String name) throws ClassNotFoundException {return clazz = loadedClasses.get(name);} 

public InputStream getResourceAsStream(String name) {return loadClassBytes.get(className);} 

надеюсь, что это помогает

EL предоставил способ очистить кэш текущего проекта, а также создание дескрипторов карт. но никто из них не работал. Не уверен, что это предполагаемое поведение или по ошибке они открыли этот API.

Gopi

Смежные вопросы