【问题标题】:Add Annotated Class in Hibernate by adding all classes in some package. JAVA通过在某个包中添加所有类来在 Hibernate 中添加带注释的类。 JAVA
【发布时间】:2011-11-14 14:09:53
【问题描述】:

有没有办法循环(例如通过 for)所有包含在某个包中的类? 我必须在AnnotationConfigurationaddAnnotatedClass(Class c)。 这样做:

    AnnotationConfiguration annotationConfiguration.addAnnotatedClass(AdditionalInformation.class);
    annotationConfiguration.addAnnotatedClass(AdditionalInformationGroup.class);
    annotationConfiguration.addAnnotatedClass(Address.class);
    annotationConfiguration.addAnnotatedClass(BankAccount.class);
    annotationConfiguration.addAnnotatedClass(City.class);
    //et cetera

我所有的表格都在 Tables.Informations 包中。

【问题讨论】:

  • 有没有机会使用 spring 或 jpa?

标签: java hibernate


【解决方案1】:

以下代码遍历指定包中的所有类,并列出带有“@Entity”注释的类。这些类中的每一个都会添加到您的 Hibernate 工厂配置中,而无需明确列出它们。

public static void main(String[] args) throws URISyntaxException, IOException, ClassNotFoundException {
    try {
        Configuration configuration = new Configuration().configure();
        for (Class cls : getEntityClassesFromPackage("com.example.hib.entities")) {
            configuration.addAnnotatedClass(cls);
        }
        sessionFactory = configuration.buildSessionFactory();
    } catch (Throwable ex) {
        System.err.println("Failed to create sessionFactory object." + ex);
        throw new ExceptionInInitializerError(ex);
    }
}

public static List<Class<?>> getEntityClassesFromPackage(String packageName) throws ClassNotFoundException, IOException, URISyntaxException {
    List<String> classNames = getClassNamesFromPackage(packageName);
    List<Class<?>> classes = new ArrayList<Class<?>>();
    for (String className : classNames) {
        Class<?> cls = Class.forName(packageName + "." + className);
        Annotation[] annotations = cls.getAnnotations();

        for (Annotation annotation : annotations) {
            System.out.println(cls.getCanonicalName() + ": " + annotation.toString());
            if (annotation instanceof javax.persistence.Entity) {
                classes.add(cls);
            }
        }
    }

    return classes;
}

public static ArrayList<String> getClassNamesFromPackage(String packageName) throws IOException, URISyntaxException, ClassNotFoundException {
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    ArrayList<String> names = new ArrayList<String>();

    packageName = packageName.replace(".", "/");
    URL packageURL = classLoader.getResource(packageName);

    URI uri = new URI(packageURL.toString());
    File folder = new File(uri.getPath());
    File[] files = folder.listFiles();
    for (File file: files) {
        String name = file.getName();
        name = name.substring(0, name.lastIndexOf('.'));  // remove ".class"
        names.add(name);
    }

    return names;
}

有用的参考:https://stackoverflow.com/a/7461653/7255

【讨论】:

    【解决方案2】:

    有一个很好的开源包,叫做“org.reflections”。你可以在这里找到它:https://github.com/ronmamo/reflections

    使用该包,您可以扫描以下实体:

    Reflections reflections = new Reflections("Tables.Informations");
    Set<Class<?>> importantClasses = reflections.getTypesAnnotatedWith(Entity.class);
    for (Class<?> clazz : importantClasses) {
        configuration.addAnnotatedClass(clazz);
    }
    

    【讨论】:

    • 这太棒了!
    【解决方案3】:

    如 cmets 中所述,使用 AnnotationConfiguration API 无法实现在包中加载所有类的功能。以下是您可以使用所述 API 执行的一些操作(请注意,“addPackage”方法仅读取包元数据,例如在 package-info.java 类中找到的元数据,它不会加载包中的所有类):

    http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html/ch01.html

    sessionFactory = new AnnotationConfiguration()
                        .addPackage("test.animals") //the fully qualified package name
                        .addAnnotatedClass(Flight.class)
                        .addAnnotatedClass(Sky.class)
                        .addAnnotatedClass(Person.class)
                        .addAnnotatedClass(Dog.class)
                        .addResource("test/animals/orm.xml")
                        .configure()
                        .buildSessionFactory();
    

    【讨论】:

    • 这到底是如何解决必须在实用程序类中写入类名的问题的? (它只节省了几次击键)。
    • @vbence 是的,同意,对不起,我的回答是错误的:无法使用 AnnotationConfiguration API 一次性添加一个包中的所有类。我给出的示例应该说明您可以做到这一点,以及一次性添加单个类和其他资源。我对 API 的误解与此处讨论的基本相同:forum.hibernate.org/viewtopic.php?f=1&t=980723 我希望我可以删除我的帖子,但我不能,因为这是一个公认的答案。
    • 哦,我读过那个(论坛帖子)。也许您可以添加一个注释,例如 “这不可能是 OP 最初想要的,但这种语法有一点帮助” 或类似的东西。
    • 你的帖子很好,对我来说很好,你没有删除它:) 事实上,我发现 addPackage 通过查看休眠源没有(我)想要的效果第一的。然后我找到了你的答案,证实了这一点。我认为在hibernate中这是非常不灵活的。应该有一种方法可以让我们从给定的包中加载所有实体类。如果使用 Spring,则该功能是可能的,但如果不使用它会怎样。
    • 这是休眠 3.5 .. 在休眠 4/5 中它是如何完成的?
    【解决方案4】:

    您可以使用 LocalSessionFactoryBuilder 来构建会话工厂,使您能够指定 scanPackages 属性。

    SessionFactory sessionFactory = new LocalSessionFactoryBuilder(hikariDataSource())
            .scanPackages("com.animals.entities")
            .addProperties(properties)
            .buildSessionFactory();
    

    【讨论】:

    • 只是补充一下,此方法仅适用于 Spring 而不是普通的 Hibernate。我猜如果 AnnotationConfiguration 正在被使用,那么 OP 正在使用普通的 Hibernate。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-08
    • 2017-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-14
    • 2015-05-03
    相关资源
    最近更新 更多