2009-09-11 171 views
36

我正在使用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> 

对于每一个I类添加到com.fooPackage我要补充一个行像这样的hibernate.cfg.xml:

<mapping class="com.fooPackage.AnotherModelClass" /> 

有没有一种方法,我可以添加新的模型类,但并不需要将此行添加到hibernate.cfg.xml?

+16

值得注意的是,''条目用于配置包本身定义的元数据,而不是包*中的类*。 – skaffman 2009-09-11 21:12:08

回答

18

开箱即用 - 无。但是,您可以编写自己的代码来检测/注册您的注释类。如果你使用Spring,你可以扩展AnnotationSessionFactoryBean和这样做:如果你不使用Spring

@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(); 
} 

(你应该:-)),您可以编写自己的代码,用于检测适当的类,通过addAnnotatedClass()方法注册您的AnnotationConfiguration

顺便说一下,除非您已经在包级别上实际声明了某些内容,否则不需要映射包。

+0

哇Chss,这是我第一次见到ClassPathScanningCandidateComponentProvider。很好。 – 2009-09-12 14:58:33

11

我刚刚遇到了这个问题,并且发现那里似乎有一个开箱即用的解决方案。我的整合还没有结束,稍后会进行更新。

从的Javadoc,尤其是packagesToScan部分:

org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean

Spring对Hibernate的, 标准的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> 

或使用类路径扫描实体类的自动检测时:

<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
著者:克林斯曼Hoeller

+0

证实,它按预期工作。 – 2011-08-09 08:27:18

+0

这也适用于我..谢谢你的回答... – 2015-09-26 21:51:25

10

这里的线程死灵位......

它仍然不像是有一种很好的方式来做你想做的事情。如果你不想使用Spring,这里是一个使用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); 

同样的方法可能是可行的其他Java反射库。

+0

请记住,这种配置方式不适用于Hibernate 5。应该改变。 – 2016-05-26 07:19:58

1

如果你不想使用spring或任何其他库,你可以实现这样的。相同的方法luke's但没有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; 
    } 
} 
0

我做的类扫描方法的一些调查,使用的答案从StackOverflow上。所以我把它们集中在一起,在一个测试项目中使用Hibernate实体扫描作为测试:hibernate-scanners-test

使用流畅,休眠

如果你没有额外的依赖关系寻找一种快速扫描的方法,你可以尝试fluent-hibernate库(你不需要有其他的罐子,图书馆除外)。 除此之外,它还具有Hibernate 5和Hibernate 4的一些有用功能,包括实体扫描,Hibernate 5隐式命名策略,嵌套变换器等。

刚刚从项目页面下载库:fluent-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
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");