[jpa] persistence.xml 구성 파일없이 JPA EntityManager 작성

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-sourcenon-jta-data-source요소는 지속성 공급자가 사용할 JTA 및 / 또는 비 JTA 데이터 소스의 전역 JNDI 이름 을 지정 하는 데 사용됩니다.

따라서 대상 Application Server가 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>

대상 Application Server가 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 공급자에 따라 다릅니다. 따라서 JPA 공급자로서 Hibernate의 경우 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);


답변

예, @Configuration 클래스 (또는 동등한 spring config 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;
}


답변

여기에 Spring이없는 솔루션이 있습니다. 상수는 다음에서 가져옵니다 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;
        }
    };
}


답변

EntityManager순전히 Java 코드 (Spring 구성 포함)를 사용하여 Hibernate 및 PostgreSQL로 다음 을 만들 수있었습니다 .

@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()nullNullPointerException

그런 다음 다음 코드로 작업했습니다.

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
}


답변

일반 JPA를 사용하면 PersistenceProvider구현 (예 : Hibernate) 이 있다고 가정 하면 PersistenceProvider # createContainerEntityManagerFactory (PersistenceUnitInfo info, Map map) 메서드를 사용 EntityManagerFactory하여 persistence.xml.

그러나 PersistenceUnitInfo인터페이스 를 구현해야한다는 것은 성가신 일이므로 persistence.xml파일 없이 JPA 부트 스트랩을 지원하는 Spring 또는 Hibernate를 사용하는 것이 좋습니다 .

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

를 Where PersistenceUnitInfo는 봄 특정에 의해 구현되는 MutablePersistenceUnitInfo의 클래스입니다.

Hibernate로이 목표를 달성하는 방법에 대한 멋진 데모를 보려면 이 기사 를 확인하십시오 .


답변

내가 사용하는 DataNucleus JPA 는 문서 에서이 작업을 수행하는 방법도 있습니다 . Spring이나 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);


답변

PersistenceContext 또는 Autowired 어노테이션을 사용하여 EntityManager를 가져올 수도 있지만 스레드로부터 안전하지 않습니다.

@PersistenceContext
private EntityManager entityManager;