EntityManager
정의 된 지속성 단위없이 초기화하는 방법이 있습니까? 엔티티 관리자를 만드는 데 필요한 모든 속성을 제공 할 수 있습니까? EntityManager
런타임에 사용자의 지정된 값에서을 만들어야합니다 . 업데이트 persistence.xml
및 재 컴파일은 옵션이 아닙니다.
이를 수행하는 방법에 대한 아이디어는 환영받는 것 이상입니다!
EntityManager
정의 된 지속성 단위없이 초기화하는 방법이 있습니까? 엔티티 관리자를 만드는 데 필요한 모든 속성을 제공 할 수 있습니까? EntityManager
런타임에 사용자의 지정된 값에서을 만들어야합니다 . 업데이트 persistence.xml
및 재 컴파일은 옵션이 아닙니다.
이를 수행하는 방법에 대한 아이디어는 환영받는 것 이상입니다!
답변:
EntityManager
정의 된 지속성 단위없이 초기화하는 방법이 있습니까?
당신은 정의해야합니다 적어도 하나 개의 퍼시스턴스 유닛을 persistence.xml
배치 기술자.
를 만드는 데 필요한 모든 속성을 제공 할 수 있습니까
Entitymanager
?
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
요소는 지속성 공급자가 사용할 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
으로 가정 할 수 있습니다.
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;
}
properties
?
여기에 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()
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
}
일반 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로이 목표를 달성하는 방법에 대한 멋진 데모를 보려면 이 기사 를 확인하십시오 .
MutablePersistenceUnitInfo
일부 메서드가 UnsupportedOperationException을 throw 하므로 사용 이 작동하지 않습니다 . 또한 언급 된 기사 는 약간 구식입니다. getPersistenceUnitRootUrl
그렇지 않으면 Hibernate가 클래스 경로를 스캔하지 않습니다 (Hibernate 5.2.8).
getPersistenceUnitRootUrl
나 getJarFileUrls
. 나중에는 stackoverflow.com/a/42372648/48136에
내가 사용하는 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);