Hibernate映射包
我正在使用Hibernate注释。
在我所有的模型类中,我都是这样注解的:
@Entity @Table public class SomeModelClass { // }
我的hibernate.cfg.xml是
<hibernate-configuration> <session-factory> <!-- some properties --> <mapping package="com.fooPackage" /> <mapping class="com.fooPackage.SomeModelClass" /> </session-factory> </hibernate-configuration>
对于添加到com.fooPackage中的每个类,我都必须在hibernate.cfg.xml中添加一行,如下所示:
<mapping class="com.fooPackage.AnotherModelClass" />
有没有办法可以添加新的模型类,但不需要将此行添加到hibernate.cfg.xml?
开箱即用 – 没有。 但是,您可以编写自己的代码来检测/注册您的注释类。 如果您使用的是Spring,那么可以扩展AnnotationSessionFactoryBean
并执行如下操作:
@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(); }
如果你不使用Spring(你应该是:-)),你可以编写自己的代码来检测适当的类,并通过addAnnotatedClass()
方法将它们注册到AnnotationConfiguration
。
顺便说一下,除非你已经在包级别上声明了一些东西,否则不需要映射包。
我只是遇到了这个问题,并发现这似乎是一个框外解决scheme。 我的整合还没有结束,稍后会更新。
从Javadoc,特别是packagesToScan
部分:
org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean
Spring的标准LocalSessionFactoryBean的子类,支持映射的JDK 1.5+注释元数据。
注意:此类需要Hibernate 3.2或更高版本,并且存在Java Persistence API和Hibernate Annotations插件。
AnnotationSessionFactoryBean
bean定义的示例:<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>
或者当使用类path扫描来自动检测实体类时:
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="packagesToScan" value="test.package"/> </bean>
从以下版本开始:1.2.2
作者:Juergen Hoeller
这里的线程死灵位
看起来好像还没有一个好方法来做你想做的事情。 如果你不想使用Spring,下面是使用reflection的类似方法:
// 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);
其他Javareflection库可能也采用相同的方法。
如果你不想使用spring
或任何其他库,你可以这样做。 与卢克的方法相同,但没有Reflections
库
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; } }
我已经做了一些类的扫描方法的调查,使用StackOverflow的答案。 所以我把所有的东西都汇集在一起,在一个testing项目中使用一个Hibernate实体扫描作为一个testing: hibernate-scanners-test 。
使用stream利的hibernate
如果你正在寻找一个快速的扫描方法,没有额外的依赖关系,你可以尝试一下stream利的Hibernate库(你不需要有其他的jar子,除了库)。 除此之外,它还具有Hibernate 5和Hibernate 4的一些有用function,包括实体扫描,Hibernate 5隐式命名策略,嵌套变换器等等。
只需从项目页面下载库: fluent-hibernate并使用EntityScanner :
对于Hibernate 4和Hibernate 5:
Configuration configuration = new Configuration(); EntityScanner.scanPackages("my.com.entities", "my.com.other.entities") .addTo(configuration); SessionFactory sessionFactory = configuration.buildSessionFactory();
使用新的Hibernate 5引导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();
1. XML <mapping class="com.concretepage.Person"/> 2. Class Configuration configuration = new Configuration().configure().addAnnotatedClass(Person.class); //Configure all the classes. Set<Class> entityClasses = new HashSet<>(Arrays.asList(Person.class,PersonDetails.class)); //Iterate all the Classes. for (Class cls : entityClasses ) { configuration.addAnnotatedClass(cls); } 3. Add package //Or you can add package configuration.addPackage("com.domain.entity");