سؤال

هل هناك طريقة لتهيئة EntityManager دون تحديد وحدة الثبات؟ هل يمكنك إعطاء جميع الخصائص المطلوبة لإنشاء مدير كيان؟ أنا بحاجة لإنشاء EntityManager من القيم المحددة للمستخدم في وقت التشغيل. تحديث persistence.xml وإعادة التجميع ليس خيارًا.

أي فكرة عن كيفية القيام بذلك أكثر من الترحيب!

هل كانت مفيدة؟

المحلول

هل هناك طريقة لتهيئة EntityManager دون تحديد وحدة الثبات؟

يجب أن تحدد على الأقل وحدة ثبات واحدة في persistence.xml واصف نشر.

هل يمكنك إعطاء جميع الخصائص المطلوبة لإنشاء ملف Entitymanager?

  • سمة الاسم مطلوبة. السمات والعناصر الأخرى اختيارية. (مواصفات JPA). لذلك يجب أن يكون هذا الحد الأدنى أو أقل persistence.xml ملف:
<persistence>
    <persistence-unit name="[REQUIRED_PERSISTENCE_UNIT_NAME_GOES_HERE]">
        SOME_PROPERTIES
    </persistence-unit>
</persistence>

في بيئات Java EE ، jta-data-source و non-jta-data-source يتم استخدام العناصر لتحديد اسم JNDI العالمي لمصدر بيانات JTA و/أو غير JTA لاستخدامها من قبل مزود الثبات.

لذلك إذا كان خادم التطبيق المستهدف يدعم JTA (JBOSS ، WebSphere ، Glassfish) ، persistence.xml يشبه:

<persistence>
    <persistence-unit name="[REQUIRED_PERSISTENCE_UNIT_NAME_GOES_HERE]">
        <!--GLOBAL_JNDI_GOES_HERE-->
        <jta-data-source>jdbc/myDS</jta-data-source>
    </persistence-unit>
</persistence>

إذا كان خادم التطبيق المستهدف لا يدعم JTA (TOMCAT) ، persistence.xml يشبه:

<persistence>
    <persistence-unit name="[REQUIRED_PERSISTENCE_UNIT_NAME_GOES_HERE]">
        <!--GLOBAL_JNDI_GOES_HERE-->
        <non-jta-data-source>jdbc/myDS</non-jta-data-source>
    </persistence-unit>
</persistence>

إذا لم يكن مصدر البيانات الخاص بك مرتبطًا بـ JNDI عالمي (على سبيل المثال ، خارج حاوية Java EE) ، فإنك عادةً ما تحدد مزود JPA ، برنامج التشغيل ، URL ، خصائص المستخدم وكلمة المرور. لكن اسم الخاصية يعتمد على مزود JPA. لذلك ، بالنسبة لـ Hibernate كمزود JPA ، الخاص بك persistence.xml سيبدو الملف مثل:

<persistence>
    <persistence-unit name="[REQUIRED_PERSISTENCE_UNIT_NAME_GOES_HERE]">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <class>br.com.persistence.SomeClass</class>
        <properties>
            <property name="hibernate.connection.driver_class" value="org.apache.derby.jdbc.ClientDriver"/>
            <property name="hibernate.connection.url" value="jdbc:derby://localhost:1527/EmpServDB;create=true"/>
            <property name="hibernate.connection.username" value="APP"/>
            <property name="hibernate.connection.password" value="APP"/>
        </properties>
    </persistence-unit>
</persistence>

سمة نوع المعاملة

بشكل عام ، في بيئات Java EE ، نوع المعاملة من RESOURCE_LOCAL يفترض أنه سيتم توفير مصدر بيانات غير JTA. في بيئة Java EE ، إذا لم يتم تحديد هذا العنصر ، فإن الافتراضي هو JTA. في بيئة Java SE ، إذا لم يتم تحديد هذا العنصر ، فهو افتراضي لـ RESOURCE_LOCAL قد يفترض.

  • لضمان قابلية تطبيق Java SE ، من الضروري أن تدرج صراحة فصول الثبات المدارة المدرجة في وحدة الثبات (مواصفات JPA)

أنا بحاجة لإنشاء EntityManager من القيم المحددة للمستخدم في وقت التشغيل

لذا استخدم هذا:

Map addedOrOverridenProperties = new HashMap();

// Let's suppose we are using Hibernate as JPA provider
addedOrOverridenProperties.put("hibernate.show_sql", true);

Persistence.createEntityManagerFactory(<PERSISTENCE_UNIT_NAME_GOES_HERE>, addedOrOverridenProperties);

نصائح أخرى

نعم ، يمكنك بدون استخدام أي ملف XML باستخدام الربيع مثل هذا داخل فئة التكوين (أو تكوين الربيع المكافئ XML):

@Bean
public LocalContainerEntityManagerFactoryBean emf(){
    properties.put("javax.persistence.jdbc.driver", dbDriverClassName);
    properties.put("javax.persistence.jdbc.url", dbConnectionURL);
    properties.put("javax.persistence.jdbc.user", dbUser); //if needed

    LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
    emf.setPersistenceProviderClass(org.eclipse.persistence.jpa.PersistenceProvider.class); //If your using eclipse or change it to whatever you're using
    emf.setPackagesToScan("com.yourpkg"); //The packages to search for Entities, line required to avoid looking into the persistence.xml
    emf.setPersistenceUnitName(SysConstants.SysConfigPU);
    emf.setJpaPropertyMap(properties);
    emf.setLoadTimeWeaver(new ReflectiveLoadTimeWeaver()); //required unless you know what your doing
    return emf;
}

تمكنت من إنشاء EntityManager مع Hibernate و PostgreSQL بحتة باستخدام رمز Java (مع تكوين الربيع) فيما يلي:

@Bean
public DataSource dataSource() {
    final PGSimpleDataSource dataSource = new PGSimpleDataSource();

    dataSource.setDatabaseName( "mytestdb" );
    dataSource.setUser( "myuser" );
    dataSource.setPassword("mypass");

    return dataSource;
}

@Bean
public Properties hibernateProperties(){
    final Properties properties = new Properties();

    properties.put( "hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect" );
    properties.put( "hibernate.connection.driver_class", "org.postgresql.Driver" );
    properties.put( "hibernate.hbm2ddl.auto", "create-drop" );

    return properties;
}

@Bean
public EntityManagerFactory entityManagerFactory( DataSource dataSource, Properties hibernateProperties ){
    final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
    em.setDataSource( dataSource );
    em.setPackagesToScan( "net.initech.domain" );
    em.setJpaVendorAdapter( new HibernateJpaVendorAdapter() );
    em.setJpaProperties( hibernateProperties );
    em.setPersistenceUnitName( "mytestdomain" );
    em.setPersistenceProviderClass(HibernatePersistenceProvider.class);
    em.afterPropertiesSet();

    return em.getObject();
}

الدعوة إلى LocalContainerEntityManagerFactoryBean.afterPropertiesSet() هو أساسى لأنه بخلاف ذلك لم يتم بناء المصنع أبدًا ، وبعد ذلك getObject() عائدات null وأنت تطارد بعد NullPointerExceptionق طوال اليوم. > :-(

ثم عملت مع الكود التالي:

PageEntry pe = new PageEntry();
pe.setLinkName( "Google" );
pe.setLinkDestination( new URL( "http://www.google.com" ) );

EntityTransaction entTrans = entityManager.getTransaction();
entTrans.begin();
entityManager.persist( pe );
entTrans.commit();

حيث كان كياني هذا:

@Entity
@Table(name = "page_entries")
public class PageEntry {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    private String linkName;
    private URL linkDestination;

    // gets & setters omitted
}

إليك حل بدون ربيع. مأخوذة من الثوابت org.hibernate.cfg.AvailableSettings :

entityManagerFactory = new HibernatePersistenceProvider().createContainerEntityManagerFactory(
            archiverPersistenceUnitInfo(),
            ImmutableMap.<String, Object>builder()
                    .put(JPA_JDBC_DRIVER, JDBC_DRIVER)
                    .put(JPA_JDBC_URL, JDBC_URL)
                    .put(DIALECT, Oracle12cDialect.class)
                    .put(HBM2DDL_AUTO, CREATE)
                    .put(SHOW_SQL, false)
                    .put(QUERY_STARTUP_CHECKING, false)
                    .put(GENERATE_STATISTICS, false)
                    .put(USE_REFLECTION_OPTIMIZER, false)
                    .put(USE_SECOND_LEVEL_CACHE, false)
                    .put(USE_QUERY_CACHE, false)
                    .put(USE_STRUCTURED_CACHE, false)
                    .put(STATEMENT_BATCH_SIZE, 20)
                    .build());

entityManager = entityManagerFactory.createEntityManager();

والسيئون PersistenceUnitInfo

private static PersistenceUnitInfo archiverPersistenceUnitInfo() {
    return new PersistenceUnitInfo() {
        @Override
        public String getPersistenceUnitName() {
            return "ApplicationPersistenceUnit";
        }

        @Override
        public String getPersistenceProviderClassName() {
            return "org.hibernate.jpa.HibernatePersistenceProvider";
        }

        @Override
        public PersistenceUnitTransactionType getTransactionType() {
            return PersistenceUnitTransactionType.RESOURCE_LOCAL;
        }

        @Override
        public DataSource getJtaDataSource() {
            return null;
        }

        @Override
        public DataSource getNonJtaDataSource() {
            return null;
        }

        @Override
        public List<String> getMappingFileNames() {
            return Collections.emptyList();
        }

        @Override
        public List<URL> getJarFileUrls() {
            try {
                return Collections.list(this.getClass()
                                            .getClassLoader()
                                            .getResources(""));
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }

        @Override
        public URL getPersistenceUnitRootUrl() {
            return null;
        }

        @Override
        public List<String> getManagedClassNames() {
            return Collections.emptyList();
        }

        @Override
        public boolean excludeUnlistedClasses() {
            return false;
        }

        @Override
        public SharedCacheMode getSharedCacheMode() {
            return null;
        }

        @Override
        public ValidationMode getValidationMode() {
            return null;
        }

        @Override
        public Properties getProperties() {
            return new Properties();
        }

        @Override
        public String getPersistenceXMLSchemaVersion() {
            return null;
        }

        @Override
        public ClassLoader getClassLoader() {
            return null;
        }

        @Override
        public void addTransformer(ClassTransformer transformer) {

        }

        @Override
        public ClassLoader getNewTempClassLoader() {
            return null;
        }
    };
}

مع JPA العادي ، على افتراض أن لديك PersistenceProvider التنفيذ (مثل السبات) ، يمكنك استخدام ProsistenceProvider#CreateContainerentityManagerFactory (InsistenceUnitInfo Info ، Map Map) طريقة لتمهيد EntityManagerFactory دون الحاجة persistence.xml.

ومع ذلك ، من المزعج أن عليك تنفيذ PersistenceUnitInfo الواجهة ، لذلك من الأفضل استخدام الربيع أو السبات الذي يدعم كلاهما bootstrapping JPA بدون أ persistence.xml ملف:

this.nativeEntityManagerFactory = provider.createContainerEntityManagerFactory(
    this.persistenceUnitInfo, 
    getJpaPropertyMap()
);

أين ال المثابرة يتم تنفيذها من قبل Spring محددة اطلاع على اطلاع صف دراسي.

الدفع هذه المقالة للحصول على مظاهرة لطيفة لكيفية تحقيق هذا الهدف مع السبات.

Datanucleus JPA التي أستخدمها لديها أيضًا طريقة للقيام بذلك في مستنداتها. لا حاجة لفصل الربيع ، أو التنفيذ القبيح ل PersistenceUnitInfo.

ببساطة تفعل على النحو التالي

import org.datanucleus.metadata.PersistenceUnitMetaData;
import org.datanucleus.api.jpa.JPAEntityManagerFactory;

PersistenceUnitMetaData pumd = new PersistenceUnitMetaData("dynamic-unit", "RESOURCE_LOCAL", null);
pumd.addClassName("mydomain.test.A");
pumd.setExcludeUnlistedClasses();
pumd.addProperty("javax.persistence.jdbc.url", "jdbc:h2:mem:nucleus");
pumd.addProperty("javax.persistence.jdbc.user", "sa");
pumd.addProperty("javax.persistence.jdbc.password", "");
pumd.addProperty("datanucleus.schema.autoCreateAll", "true");

EntityManagerFactory emf = new JPAEntityManagerFactory(pumd, null);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top