[ACCEPTED]-Hibernate Mapping Package-hibernate-annotations
Out of the box - no. You can write your 9 own code to detect / register your annotated 8 classes, however. If you're using Spring, you 7 can extend AnnotationSessionFactoryBean
and do something like:
@Override
protected SessionFactory buildSessionFactory() throws Exception {
ArrayList<Class> classes = new ArrayList<Class>();
// the following will detect all classes that are annotated as @Entity
ClassPathScanningCandidateComponentProvider scanner =
new ClassPathScanningCandidateComponentProvider(false);
scanner.addIncludeFilter(new AnnotationTypeFilter(Entity.class));
// only register classes within "com.fooPackage" package
for (BeanDefinition bd : scanner.findCandidateComponents("com.fooPackage")) {
String name = bd.getBeanClassName();
try {
classes.add(Class.forName(name));
} catch (Exception E) {
// TODO: handle exception - couldn't load class in question
}
} // for
// register detected classes with AnnotationSessionFactoryBean
setAnnotatedClasses(classes.toArray(new Class[classes.size()]));
return super.buildSessionFactory();
}
If you're 6 not using Spring (and you should be :-) ) you 5 can write your own code for detecting appropriate 4 classes and register them with your AnnotationConfiguration
via 3 addAnnotatedClass()
method.
Incidentally, it's not necessary 2 to map packages unless you've actually declared 1 something at package level.
I just come across this problem, and find 12 out there seems an out of box solution for 11 this. My integration is not out yet, will 10 update this later.
From the Javadoc, especially 9 the packagesToScan
part:
org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean
Subclass of Spring's standard 8 LocalSessionFactoryBean for Hibernate, supporting 7 JDK 1.5+ annotation metadata for mappings.
Note: This 6 class requires Hibernate 3.2 or later, with 5 the Java Persistence API and the Hibernate 4 Annotations add-on present.
Example for an 3
AnnotationSessionFactoryBean
bean definition:<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="annotatedClasses"> <list> <value>test.package.Foo</value> <value>test.package.Bar</value> </list> </property> </bean>
Or when using classpath 2 scanning for autodetection of entity classes:
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="packagesToScan" value="test.package"/> </bean>
Since: 1.2.2
Author: Juergen 1 Hoeller
Bit of thread necromancy here...
It still 5 doesn't look like there's a good way to 4 do what you want. If you don't want to 3 use Spring, here's a similar method using 2 Reflections:
// Create your SessionFactory with mappings for every `Entity` in a specific package
Configuration configuration = new Configuration();
configuration.configure("your_hibernate.cfg.xml");
Reflections reflections = new Reflections("your_package");
Set<Class<?>> classes = reflections.getTypesAnnotatedWith(javax.persistence.Entity.class);
for(Class<?> clazz : classes)
{
configuration.addAnnotatedClass(clazz);
}
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
The same approach is probably viable for 1 other Java reflection libraries.
If you do not want to use spring
or any other 2 library, you can achieve that like this. Same 1 approach as luke's but without Reflections
library
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import javax.persistence.Entity;
import javax.tools.FileObject;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
public class SessionFactoryWrapper {
private final SessionFactory sessionFactory;
public SessionFactoryWrapper(final String...packagesToScan) {
this.sessionFactory = this.createSessionFactory(packagesToScan);
}
private SessionFactory createSessionFactory(final String[] packagesToScan) {
final Configuration configuration = new Configuration();
configuration.configure(); // Reads hibernate.cfg.xml from classpath
for (String packageToScan : packagesToScan) {
this.getEntityClasses(packageToScan).stream().forEach( configuration::addAnnotatedClass);
}
final ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
return configuration.buildSessionFactory(serviceRegistry);
}
private Collection<Class> getEntityClasses(final String pack) {
final StandardJavaFileManager fileManager = ToolProvider.getSystemJavaCompiler().getStandardFileManager(null, null, null);
try {
return StreamSupport.stream(fileManager.list(StandardLocation.CLASS_PATH, pack, Collections.singleton(JavaFileObject.Kind.CLASS), false).spliterator(), false)
.map(FileObject::getName)
.map(name -> {
try {
final String[] split = name
.replace(".class", "")
.replace(")", "")
.split(Pattern.quote(File.separator));
final String fullClassName = pack + "." + split[split.length - 1];
return Class.forName(fullClassName);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
})
.filter(aClass -> aClass.isAnnotationPresent(Entity.class))
.collect(Collectors.toCollection(ArrayList::new));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public SessionFactory getSessionFactory() {
return sessionFactory;
}
}
I have done some investigations of class 13 scanning approaches, using answers from 12 StackOverflow. So I gather all it together, using 11 a Hibernate entities scanning as a test, in 10 the one test project: hibernate-scanners-test.
Using fluent-hibernate
If you are looking 9 for a quick scanning approach without additional 8 dependencies, you can try fluent-hibernate library (you 7 will not need to have other jars, except 6 the library). Apart this, it has some useful 5 features for Hibernate 5 and Hibernate 4, including 4 entities scanning, a Hibernate 5 implicit 3 naming strategy, a nested transformer and 2 others.
Just download the library from the 1 project page: fluent-hibernate and use EntityScanner:
For Hibernate 4 and Hibernate 5:
Configuration configuration = new Configuration();
EntityScanner.scanPackages("my.com.entities", "my.com.other.entities")
.addTo(configuration);
SessionFactory sessionFactory = configuration.buildSessionFactory();
Using a new Hibernate 5 bootstrapping API:
List<Class<?>> classes = EntityScanner
.scanPackages("my.com.entities", "my.com.other.entities").result();
MetadataSources metadataSources = new MetadataSources();
for (Class<?> annotatedClass : classes) {
metadataSources.addAnnotatedClass(annotatedClass);
}
SessionFactory sessionFactory = metadataSources.buildMetadata()
.buildSessionFactory();
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.