11

is there any way to loop (e.g. via for) all classes with are in some package? I have to addAnnotatedClass(Class c) on AnnotationConfiguration. Doing it like this:

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

All of my tables are in package Tables.Informations.

Michał Skóra
  • 351
  • 2
  • 6
  • 18

4 Answers4

14

As mentioned in the comments, the functionality of loading all classes in a package is not possible with the AnnotationConfiguration API. Here's some of the stuff you can do with said API (note that the "addPackage" method only reads package metadata, such as that found in the package-info.java class, it does NOT load all classes in package):

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();
Shivan Dragon
  • 15,004
  • 9
  • 62
  • 103
  • 3
    How on earth does this solve the problem of having to burn in the class names in your utility class? (It only saves a few keystrokes). – vbence Mar 26 '14 at 09:11
  • 3
    @vbence Yes, agreed, I'm sorry, my answer is wrong: there's no way to add all classes from one package in one go using the AnnotationConfiguration API. The example I give was supposed to illustrate that you can do this, as well as add individual classes and other resources all in one go. I've basicaly had the same misunderstanding on the API as the one discussed here: https://forum.hibernate.org/viewtopic.php?f=1&t=980723 I wish I could delete my post, but I can't because it's an accepted answer. – Shivan Dragon Mar 26 '14 at 16:21
  • 2
    Oh, I read that one (forum post). Maybe you can add a note like *"it is not possible what the OP originnaly wanted, but this syntax helps a little"* or something like that. – vbence Mar 26 '14 at 16:32
  • 1
    You post is fine, good for me that you didn't delete it :) In fact I found that `addPackage` doesn't have the desired (by me) effect by looking at the hibernate sources first. Then I found your answer which confirms it. This is very inflexibly done in my opinion in hibernate. There should be a method to allow us to load all entity classes from a given package. That functionality is possible if one uses Spring but what if one doesn't use it. – peter.petrov Jan 23 '15 at 14:57
  • 1
    this is hibernate 3.5 .. how is it done in hibernat 4/5 ? – mjs Jan 20 '21 at 20:23
  • @mmm Hibernate 4.3 still doesn't support this. Beyond that I haven't tried this anymore. I prefer using Spring instead (which under the good uses JPA/Hibernate). Spring has some very simple and clear annotations that allows you to pick up entities from a certain package – Shivan Dragon Mar 08 '21 at 08:51
  • I hate Spring. Also requires you to be tied to hard. You can not static void main and get access. I was able to get it to work without spring eventually. not using this. – mjs Mar 09 '21 at 11:07
12

The following code goes through all the classes within a specified package and makes a list of those annotated with "@Entity". Each of those classes is added into your Hibernate factory configuration, without having to list them all explicitly.

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;
}

Helpful reference: https://stackoverflow.com/a/7461653/7255

Community
  • 1
  • 1
Steve Pitchers
  • 7,088
  • 5
  • 41
  • 41
5

There is a nice open source package called "org.reflections". You can find it here: https://github.com/ronmamo/reflections

Using that package, you can scan for entities like this:

Reflections reflections = new Reflections("Tables.Informations");
Set<Class<?>> importantClasses = reflections.getTypesAnnotatedWith(Entity.class);
for (Class<?> clazz : importantClasses) {
    configuration.addAnnotatedClass(clazz);
}
Matthias Bohlen
  • 598
  • 6
  • 12
2

You can use LocalSessionFactoryBuilder for building session factory that enables you to specify scanPackages property.

SessionFactory sessionFactory = new LocalSessionFactoryBuilder(hikariDataSource())
        .scanPackages("com.animals.entities")
        .addProperties(properties)
        .buildSessionFactory();
Suchac
  • 91
  • 5
  • 2
    just to add, this method works only with Spring and not plain Hibernate. I guess if `AnnotationConfiguration` is being used, then OP is using plain Hibernate. – Archit May 20 '19 at 11:11