Jpa Eclipselink实体映射缓存
我正在为我的项目使用EclipseLink。 我扩展了XMLMetadataSource(以提供自定义类加载器),因为我持久化的实体是运行时创建的。它工作正常 当我执行以下操作时,我得到了“未知实体类型”Jpa Eclipselink实体映射缓存,jpa,orm,mapping,eclipselink,entitymanager,Jpa,Orm,Mapping,Eclipselink,Entitymanager,我正在为我的项目使用EclipseLink。 我扩展了XMLMetadataSource(以提供自定义类加载器),因为我持久化的实体是运行时创建的。它工作正常 当我执行以下操作时,我得到了“未知实体类型” 创建实体 创建映射 创建实体管理器工厂,提供自定义类加载器 创建实体管理器并持久化。-它工作正常 现在删除实体,并从类加载器中删除 创建相同的实体 再次创建映射(当然看起来是一样的) 尝试使用新属性(新类加载器、映射文件)刷新实体管理器工厂 尝试坚持-抱怨“未知类型” 如果EL缓存XML映
- 创建实体
- 创建映射
- 创建实体管理器工厂,提供自定义类加载器
- 创建实体管理器并持久化。-它工作正常
- 现在删除实体,并从类加载器中删除
- 创建相同的实体
- 再次创建映射(当然看起来是一样的)
- 尝试使用新属性(新类加载器、映射文件)刷新实体管理器工厂
- 尝试坚持-抱怨“未知类型”
相同的结果。是的,持久性单元加载只执行一次。如果使用XMLMetadataSource更改映射,则必须告诉工厂使用EMF上的refreshMetadata()刷新其映射,如下所述:
之后,获得的下一个EntityManager将使用新的映射,而现有的EMs仍将使用旧的映射。我在eclipse链接中提交了一个bug
这不是EL中的一个漏洞。但问题在于EL“没有构建或重新创建“类-->类描述符”映射(一个包含每个实体的类对象和实体描述的内部映射)。我偶然发现了这一点。对于那些感兴趣的人,这里有一个示例代码可能会有所帮助
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);
}
公共类Test1{
公共测试1(字符串pu、地图道具){
pu_name=pu;
properties=newhashmap();
属性。putAll(道具);
loader=新的MyClassLoader();
}
公共无效初始化(){
mms=新的WAMetadataSource();
properties.put(PersistenceUnitProperties.METADATA\u源,mms);
properties.put(PersistenceUnitProperties.CLASSLOADER,loader);
如果(emf==null | |!emf.isOpen()){
已同步(Test1.class){
如果(emf==null | |!emf.isOpen()){
emf=Persistence.createEntityManagerFactory(pu_名称、属性);
}
}
}否则{
getEntityManagerFactory(emf).refreshMetadata(属性);
}
System.out.println(“=======>refreshed.emf.hascode:“+emf.hashCode()+”,loader.h:“+loader.hashCode()”);
}公共实体管理器getEntityManager(地图道具){
if(em==null){
em=emf.createEntityManager(道具);
}
返回em;
}公共void持久化(对象obj){
试一试{
getEntityManager(属性);
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();
}最后{
}
}公共对象getRuntimeEntityObject(int ii){
objectobj=null;
Class clazz=loader.loadClass(“com.xxx.sample.entity.runtime.User”);
如果(ii==1){
obj=clazz.getConstructor(String.class).newInstance(“Jai-Ramjiki-1”);
}否则{
obj=clazz.getConstructor(String.class).newInstance(“Jai-Ramjiki-2”);
}
obj=分层铸造(obj);
返回obj;
}公共静态void main(字符串[]args){
Map props=newhashmap();
put(PersistenceUnitProperties.JDBC_驱动程序,“com.mysql.JDBC.DRIVER”);
put(PersistenceUnitProperties.JDBC_URL,“JDBC:mysql://localhost:3306/test" );
put(PersistenceUnitProperties.JDBC_用户,“root”);
put(PersistenceUnitProperties.JDBC_密码,“root”);
put(PersistenceUnitProperties.DDL_生成,“创建或扩展表”);
test1t1=newtest1(“mysql”,props);
Object obj1=t1.getRuntimeEntityObject(1);
System.out.println(“*****>obj1=“+obj1+”,类加载器哈希代码:“+obj1.getClass().getClassLoader().hashcode());
t1.初始化();
t1.持久化(obj1);
System.out.println(“类1:+obj1.getClass().hashCode()+”,obj1:+obj1);
t1.close();
//现在删除前面的类装入器并重新运行相同的类装入器。
test1t2=newtest1(“mysql”,props);
Object obj2=t2.getRuntimeEntityObject(2);
System.out.println(“*****>obj2=“+obj2+”,类加载器hashcode:“+obj2.getClass().getClassLoader().hashcode()”);
t2.初始化();
t2.持续存在(obj2);
t2.关闭();
objectobj3=t1.getRuntimeEntityObject(1);
System.out.println(“**>obj3=“+obj3+”,类加载器哈希代码:“+obj3.getClass().getClassLoader().hashcode());
t1.持久性(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);
}
@覆盖
公共XMLEntityMappings getEntityMappings(映射属性、类加载器类加载器、会话日志){
put(PersistenceUnitProperties.METADATA_SOURCE_XML_文件,“eclipselink orm user.XML”);
properties.put(PersistenceUnitProperties.VALIDATOR_FACTORY,null);
返回super.getEntityMappings(属性、类加载器、日志);
}
并在CustomClassloader中使用javassist创建一个运行时类,该类扩展了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);
}
public void createRuntimeClass(字符串类名称)引发异常{
CtClass bclass=pool.makeClass(类名);
bclass.addConstructor(CtNewConstructor.defaultConstructor(bclass));
映射字段=新的HashMap();
添加字段(字段);
int noOfFields=fields.size();
CtClass[]fclasses=新CtClass[noOfFields];
int ii=0;
for(输入字段:fields.entrySet()){
字符串fieldName=field.getKey();
字符串fieldType=field.getValue();
//
public Class<?> loadClass(String name) throws ClassNotFoundException {return clazz = loadedClasses.get(name);}
public InputStream getResourceAsStream(String name) {return loadClassBytes.get(className);}