Разве это не раздражает, когда вам приходится добавлять каждый класс отдельно в конфигурацию Spring, когда вы имеете дело с аннотированными классами? Бьюсь об заклад, это раздражает вас еще больше, когда вам нужно реорганизовать пакет, а Eclipse не реорганизует пакет внутри XML-файла. У меня есть ваше решение, и оно вам ничего не будет стоить.
Сначала вам нужно написать свой XML так же, как мой.
<!-- add dynamic factory here --><bean id="sessionFactory"class="com.package.spring.AutomatedAnnotationSessionFactoryBean"><property name="dataSource" ref="dataSource" /><property name="automaticAnnotatedPackages"><list><value>com.package.domain</value><value>com.package.domain.view</value></list></property><property name="annotatedPackages"><list><value>com.package.domain</value><value>com.package.domain.view</value></list></property><!-- annotated source files --><!-- <property name="annotatedClasses"><list><value>example.Account</value><value>example.AccountDetail</value><value>example.Employee</value></list></property> --><property name="hibernateProperties"><props><prop key="hibernate.generate_statistics">true</prop><prop key="hibernate.dialect">${db.dialect}</prop><prop key="hibernate.cache.provider_class">${cache.provider}</prop><!-- <prop key="hibernate.cache.provider_class">org.hibernate.cache.TreeCacheProvider</prop> --><prop key="hibernate.show_sql">false</prop><!-- <prop key="hibernate.hbm2ddl.auto">create</prop> --><prop key="hibernate.validator.apply_to_ddl">true</prop><!-- <prop key="hibernate.validator.autoregister_listeners">true</prop><prop key="hibernate.validator.apply_to_ddl">true</prop><prop key="hibernate.cache.use_query_cache">true</prop> --><!-- <prop key="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</prop> --></props></property></bean>
Вы очень быстро заметите, что вам также нужен новый класс.
public class AutomatedAnnotationSessionFactoryBean extends LocalSessionFactoryBean{ private Class[] annotatedClasses; private String[] annotatedPackages; private String[] automaticAnnotatedPackages; private static Log log = LogFactory .getLog(AutomatedAnnotationSessionFactoryBean.class); public String[] getAutomaticAnnotatedPackages() { return automaticAnnotatedPackages; } public void setAutomaticAnnotatedPackages(String[] annotatedPackages) { automaticAnnotatedPackages = annotatedPackages; } public AutomatedAnnotationSessionFactoryBean() { setConfigurationClass(AnnotationConfiguration.class); } public void setConfigurationClass(Class configurationClass) { if (configurationClass == null || !AnnotationConfiguration.class .isAssignableFrom(configurationClass)) { throw new IllegalArgumentException( "AnnotationSessionFactoryBean only supports AnnotationConfiguration or subclasses"); } super.setConfigurationClass(configurationClass); } /** * Specify annotated classes, for which mappings will be read from * class-level JDK 1.5+ annotation metadata. * * @see org.hibernate.cfg.AnnotationConfiguration#addAnnotatedClass(Class) */ public void setAnnotatedClasses(Class[] annotatedClasses) { this.annotatedClasses = annotatedClasses; } /** * Specify the names of annotated packages, for which package-level JDK 1.5+ * annotation metadata will be read. * * @see org.hibernate.cfg.AnnotationConfiguration#addPackage(String) */ public void setAnnotatedPackages(String[] annotatedPackages) { this.annotatedPackages = annotatedPackages; } /** * Reads metadata from annotated classes and packages into the * AnnotationConfiguration instance. * <p> * Calls <code>postProcessAnnotationConfiguration</code> afterwards, to give * subclasses the chance to perform custom post-processing. * * @see #postProcessAnnotationConfiguration */ protected final void postProcessConfiguration(Configuration config) throws HibernateException { AnnotationConfiguration annConfig = (AnnotationConfiguration) config; if (this.annotatedClasses != null) { for (int i = 0; i < this.annotatedClasses.length; i++) { annConfig.addAnnotatedClass(this.annotatedClasses[i]); } } if (this.annotatedPackages != null) { for (int i = 0; i < this.annotatedPackages.length; i++) { annConfig.addPackage(this.annotatedPackages[i]); } } try { if (this.automaticAnnotatedPackages != null) { for (int i = 0; i < this.automaticAnnotatedPackages.length; i++) { List<String> classList = ResourceLocator.getClassesInPackage( automaticAnnotatedPackages[i], new ArrayList<String>() { }, false); for (String clazz : classList) { log.info("Found a Class: " + clazz); Class thisClass = Class.forName(clazz); if (thisClass.isAnnotationPresent(Hibernate.class)) { log.debug("Adding Mapped Package - CLASS: " + clazz); annConfig.addAnnotatedClass(thisClass); addMetaData(thisClass); } } } } } catch (Exception e) { throw new HibernateException(e); } // Perform custom post-processing in subclasses. postProcessAnnotationConfiguration(annConfig); } private static void addMetaData(Class clazz) throws Exception { EntityMetaData metaData = new EntityMetaDataImpl(); Method[] methods = clazz.getMethods(); for (int i = 0; i < methods.length; i++) { Method method = methods[i]; log.debug("Adding method: " + method.getName()); metaData.addMethod(method.getName(), method.getReturnType()); if (method.isAnnotationPresent(FriendlyName.class)) { metaData.setFriendlyName(method.getName()); } } if (clazz.isAnnotationPresent(Table.class)) { Table table = (Table) clazz.getAnnotation(Table.class); metaData.setTableName(table.name()); } if (clazz.isAnnotationPresent(Entity.class)) { Entity entity = (Entity) clazz.getAnnotation(Entity.class); if (entity.name() != null && !StringUtil.isEmpty(entity.name())) metaData.setEntityName(entity.name()); else metaData.setEntityName(clazz.getSimpleName()); } if (clazz.isAnnotationPresent(Auditable.class)) metaData.setAuditable(true); if (clazz.isAnnotationPresent(Cache.class)) metaData.setCache(true); if (clazz.isAnnotationPresent(DefaultSort.class)) { String[] fields = ((DefaultSort) clazz .getAnnotation(DefaultSort.class)).fields(); SortDirection[] directions = ((DefaultSort) clazz .getAnnotation(DefaultSort.class)).directions(); Set<ExtOrder> sorts = new LinkedHashSet<ExtOrder>(); for (int i = 0; i < fields.length; i++) { sorts.add(new ExtOrder(fields[i], directions[i], true)); } metaData.setDefaultSort(sorts); } if (clazz.isAnnotationPresent(Proxy.class)) { Proxy proxy = (Proxy) clazz.getAnnotation(Proxy.class); metaData.setLazy(proxy.lazy()); } log.debug("Adding meta data for Class: " + clazz); SpringLoader.addEntityMetaData(clazz, metaData); } /** * To be implemented by subclasses that want to to perform custom * post-processing of the AnnotationConfiguration object after this * FactoryBean performed its default initialization. * * @param config * the current AnnotationConfiguration object * @throws HibernateException * in case of Hibernate initialization errors */ protected void postProcessAnnotationConfiguration( AnnotationConfiguration config) throws HibernateException { } public SessionFactory getCurrentSessionFactory() { return getSessionFactory(); } public Map<String, EntityMetaData> getEntityMetaData() { return SpringLoader.getEntityMetaData(); }}
Свойство, на которое вы хотите обратить внимание в файле конфигурации, — AutomaticAnnotatedPackages. Это делает всю магию. Мой пользовательский класс будет проходить через перечисленные пакеты и искать аннотацию @Hibernate. Это аннотация, которую вы должны будете создать. Вы можете назвать это как угодно, но вам просто нужно это найти. Вы найдете его, отобразите свои классы в классе, и вы уже в работе. Больше не нужно перечислять каждый класс в отдельности.