java हाइबरनेट मैपिंग पैकेज




hibernate hibernate-annotations (5)

मैं हाइबरनेट एनोटेशन का उपयोग कर रहा हूं।

मेरे सभी मॉडल वर्गों में मैं इस तरह एनोटेट करता हूं:

@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 या किसी अन्य पुस्तकालय का उपयोग नहीं करना चाहते हैं, तो आप इसे इस तरह प्राप्त कर सकते हैं। 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;
    }
}

बॉक्स के बाहर - नहीं। हालांकि, आप अपनी एनोटेटेड कक्षाओं का पता लगाने / पंजीकरण करने के लिए अपना कोड लिख सकते हैं। यदि आप वसंत का उपयोग कर रहे हैं, तो आप 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();
}

यदि आप स्प्रिंग का उपयोग नहीं कर रहे हैं (और आपको होना चाहिए :-)) आप उचित कक्षाओं का पता लगाने के लिए अपना कोड लिख सकते हैं और addAnnotatedClass() विधि के माध्यम से उन्हें अपनी AnnotationConfiguration addAnnotatedClass() साथ पंजीकृत कर सकते हैं।

संयोग से, पैकेजों को मैप करना जरूरी नहीं है जबतक कि आपने वास्तव में पैकेज स्तर पर कुछ घोषित नहीं किया है।


थ्रेड necromancy के बिट यहाँ ...

यह अभी भी ऐसा नहीं लगता है कि आप जो चाहते हैं उसे करने का एक अच्छा तरीका है। यदि आप वसंत का उपयोग नहीं करना चाहते हैं, तो 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);

अन्य जावा प्रतिबिंब पुस्तकालयों के लिए एक ही दृष्टिकोण संभवतः व्यवहार्य है।


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");

मैं बस इस समस्या को पूरा करता हूं, और पता लगाता हूं कि इसके लिए बॉक्स समाधान से बाहर निकलता है। मेरा एकीकरण अभी तक बाहर नहीं है, इसे बाद में अपडेट करेगा।

जावाडोक से, विशेष रूप से packagesToScan ToScan भाग:

org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean

स्प्रिंग के मानक स्थानीय सत्र फ़ैब्रिकबीन के उप-वर्ग, हाइबरनेट के लिए, मैपिंग के लिए जेडीके 1.5+ एनोटेशन मेटाडेटा का समर्थन करते हुए।

नोट: इस कक्षा को जावा पर्सिस्टेंस एपीआई और हाइबरनेट एनोटेशन ऐड-ऑन के साथ हाइबरनेट 3.2 या उसके बाद की आवश्यकता है।

AnnotationSessionFactoryBean लिए उदाहरण AnnotationSessionFactoryBean बीन परिभाषा:

<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
लेखक: जुर्गेन होलर





hibernate-annotations