Hi!
We are developing a web based graphical database: Vaadin (GUI) with a generic layer for DB access supporting Hibernate & JPA (EclipseLink, HibernateJPA and ObjectDB). Works fine. But now we are trying to find a general solution for control the @Table/@Index attributes.
Static annotaions in the source code like
@Table(indexes = { @Index(columnList = "ci"),@Index(columnList = "uiElement"),@Index(columnList = "histId")})
work fine.
But now we try to use dynamic modfied annotations. See the code at the end of the posting. With this approach you can collect the @Index attributes over all subclasses and create a new @Table annotation, or create DB specific @Index. This tricky code works fine for Hibernate. But for EclipseLink the modified annotation/class is ignored by EclipseLink. The custom PersistenceUnitProperties.CLASSLOADER works, but this loader is called after table creation. The table creation process uses the unmodified annotations/class invoking an other class loader.
Any idea to solve this tricky problem.
with best regards.
Peter
public class ChangeAnnotation {
public static void test(Class<?> clazz) {
Annotation a = clazz.getAnnotation(Table.class);
Table t = (Table) a;
for (Index i : t.indexes()) {
System.out.println(i.columnList());
}
}
public static Index createIndex(final String columnList) {
return (Index) Proxy.newProxyInstance(Index.class.getClassLoader(),
new Class[] { Index.class }, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method,
Object[] args) {
if (method.getName().equals("columnList")) {
return columnList;
} else {
return "";
}
}
});
}
private static void collectIndexes(final Class<?> clazz,
ArrayList<Index> list) {
Annotation a = clazz.getAnnotation(Table.class);
Table t = (Table) a;
for (Index i : t.indexes()) {
list.add(i);
}
Class<?> s = clazz.getSuperclass();
Annotation mapped = s.getAnnotation(MappedSuperclass.class);
if (mapped != null) {
collectIndexes(s, list);
}
}
public static void rebuildIndexAnnotations(final Class<?> clazz)
throws Exception {
Annotation a = Class.forName(clazz.getName()).getAnnotation(Table.class);
if(a == null) {
return;
}
ArrayList<Index> list = new ArrayList<Index>();
collectIndexes(clazz, list);
Table t = (Table) a;
if (list.size() > 0 && (t.indexes().length != list.size())) {
Object invocationHandler = Proxy.getInvocationHandler(a);
Field field = invocationHandler.getClass().getDeclaredField(
"memberValues");
field.setAccessible(true);
LinkedHashMap<String, Object[]> map = (LinkedHashMap<String, Object[]>) field
.get(invocationHandler);
map.put("indexes", list.toArray(new Index[list.size()]));
field.set(invocationHandler, map);
}
}
public static void main(String args[]) throws Exception {
rebuildIndexAnnotations(CIimage.class);
test(CIimage.class);
}
}