Bạn có thể chỉ định tên bảng vào thời gian tải thông qua tùy chỉnh ClassLoader ghi lại chú thích @Table
trên các lớp khi chúng được tải. Tại thời điểm này, tôi không chắc chắn 100% cách bạn sẽ bảo đảm Hibernate đang tải các lớp của nó thông qua ClassLoader này.
Lớp học được viết lại bằng the ASM bytecode framework.
Cảnh báo: Các lớp này là thử nghiệm.
public class TableClassLoader extends ClassLoader {
private final Map<String, String> tablesByClassName;
public TableClassLoader(Map<String, String> tablesByClassName) {
super();
this.tablesByClassName = tablesByClassName;
}
public TableClassLoader(Map<String, String> tablesByClassName, ClassLoader parent) {
super(parent);
this.tablesByClassName = tablesByClassName;
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
if (tablesByClassName.containsKey(name)) {
String table = tablesByClassName.get(name);
return loadCustomizedClass(name, table);
} else {
return super.loadClass(name);
}
}
public Class<?> loadCustomizedClass(String className, String table) throws ClassNotFoundException {
try {
String resourceName = getResourceName(className);
InputStream inputStream = super.getResourceAsStream(resourceName);
ClassReader classReader = new ClassReader(inputStream);
ClassWriter classWriter = new ClassWriter(0);
classReader.accept(new TableClassVisitor(classWriter, table), 0);
byte[] classByteArray = classWriter.toByteArray();
return super.defineClass(className, classByteArray, 0, classByteArray.length);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private String getResourceName(String className) {
Type type = Type.getObjectType(className);
String internalName = type.getInternalName();
return internalName.replaceAll("\\.", "/") + ".class";
}
}
Các TableClassLoader
dựa trên TableClassVisitor
để bắt phương pháp visitAnnotation gọi:
public class TableClassVisitor extends ClassAdapter {
private static final String tableDesc = Type.getDescriptor(Table.class);
private final String table;
public TableClassVisitor(ClassVisitor visitor, String table) {
super(visitor);
this.table = table;
}
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
AnnotationVisitor annotationVisitor;
if (desc.equals(tableDesc)) {
annotationVisitor = new TableAnnotationVisitor(super.visitAnnotation(desc, visible), table);
} else {
annotationVisitor = super.visitAnnotation(desc, visible);
}
return annotationVisitor;
}
}
Các TableAnnotationVisitor
là cuối cùng chịu trách nhiệm về thay đổi name
lĩnh vực @Table
chú thích:
public class TableAnnotationVisitor extends AnnotationAdapter {
public final String table;
public TableAnnotationVisitor(AnnotationVisitor visitor, String table) {
super(visitor);
this.table = table;
}
@Override
public void visit(String name, Object value) {
if (name.equals("name")) {
super.visit(name, table);
} else {
super.visit(name, value);
}
}
}
Vì Tôi đã không tìm thấy một số AnnotationAdapter
lớp trong thư viện ASM của, đây là một trong tôi đã thực hiện bản thân mình:
public class AnnotationAdapter implements AnnotationVisitor {
private final AnnotationVisitor visitor;
public AnnotationAdapter(AnnotationVisitor visitor) {
this.visitor = visitor;
}
@Override
public void visit(String name, Object value) {
visitor.visit(name, value);
}
@Override
public AnnotationVisitor visitAnnotation(String name, String desc) {
return visitor.visitAnnotation(name, desc);
}
@Override
public AnnotationVisitor visitArray(String name) {
return visitor.visitArray(name);
}
@Override
public void visitEnd() {
visitor.visitEnd();
}
@Override
public void visitEnum(String name, String desc, String value) {
visitor.visitEnum(name, desc, value);
}
}
Bạn có cần làm việc với nhiều bảng (với cùng một JPA @Entity) trong mỗi lần thực hiện chương trình hay chỉ là một bảng cho mỗi lần thực hiện? – mtpettyp
Có khả năng bất kỳ số lượng bảng nào - điều này rất có thể sẽ là một ứng dụng web –