2010-01-01 33 views
63

Có cách nào để khởi tạo EntityManager mà không có đơn vị được xác định không? Bạn có thể cung cấp tất cả các thuộc tính bắt buộc để tạo trình quản lý đối tượng không? Tôi cần tạo EntityManager từ giá trị được chỉ định của người dùng khi chạy. Cập nhật persistence.xml và biên dịch lại không phải là một tùy chọn.Tạo JPA EntityManager không có tệp cấu hình persistence.xml

Bất kỳ ý tưởng nào về cách thực hiện điều này đều được hoan nghênh!

Trả lời

53

Có cách nào để khởi tạo EntityManager mà không có đơn vị liên tục được xác định không?

Bạn nên xác định ít nhất một đơn vị kiên trì trong mô tả persistence.xml triển khai.

Bạn có thể cung cấp tất cả các thuộc tính bắt buộc để tạo một Entitymanager không?

  • Thuộc tính tên là bắt buộc. Các thuộc tính và phần tử khác là tùy chọn. (Đặc điểm kỹ thuật JPA). Vì vậy, điều này nên được nhiều hơn hoặc ít hơn mức tối thiểu của bạn persistence.xml file:
<persistence> 
    <persistence-unit name="[REQUIRED_PERSISTENCE_UNIT_NAME_GOES_HERE]"> 
     SOME_PROPERTIES 
    </persistence-unit> 
</persistence> 

Trong môi trường Java EE, các jta-data-sourcenon-jta-data-source yếu tố được sử dụng để xác định tên JNDI toàn cầu của JTA và/hoặc phi Nguồn dữ liệu JTA sẽ được nhà cung cấp kiên trì sử dụng.

Vì vậy, nếu bạn máy chủ mục tiêu ứng dụng hỗ trợ JTA (JBoss, Websphere, GlassFish), persistence.xml của bạn trông giống như:

<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> 

Nếu Server của bạn mục tiêu ứng dụng không hỗ trợ JTA (Tomcat), persistence.xml vẻ của bạn như:

<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> 

Nếu nguồn dữ liệu của bạn không bị ràng buộc với JNDI toàn cầu (ví dụ, bên ngoài thùng chứa Java EE), vì vậy bạn thường định nghĩa nhà cung cấp JPA, trình điều khiển, u thuộc tính rl, người dùng và mật khẩu. Nhưng tên thuộc tính tùy thuộc vào nhà cung cấp JPA. Vì vậy, đối với Hibernate là nhà cung cấp JPA, persistence.xml tập tin của bạn sẽ trông giống như:

<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> 

Loại giao dịch Thuộc tính

Nói chung, trong môi trường Java EE, một giao dịch loại RESOURCE_LOCAL giả định rằng một phi Nguồn dữ liệu JTA sẽ được cung cấp. Trong môi trường Java EE, nếu phần tử này không được chỉ định, mặc định là JTA. Trong môi trường Java SE, nếu phần tử này không được chỉ định, mặc định là RESOURCE_LOCAL có thể được giả định.

  • Để đảm bảo tính di động của một ứng dụng Java SE, nó là cần thiết để một cách rõ ràng danh sách các lớp kiên trì quản lý được bao gồm trong các đơn vị bền vững (JPA đặc điểm kỹ thuật)

tôi cần tạo EntityManager từ giá trị được chỉ định của người dùng tại thời gian chạy

Vì vậy, sử dụng này:

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); 
+0

Hi Tôi cố gắng giải pháp của bạn, nhưng gặp sự cố, bạn có thể xin vui lòng kiểm tra câu hỏi của tôi: http://stackoverflow.com/ câu hỏi/3935394/how-to-externalize-properties-from-jpas-persistence-xml – stacker

+0

@stacker Tôi đang kiểm tra –

21

Có bạn có thể mà không sử dụng bất kỳ tập tin xml sử dụng mùa xuân như thế này bên trong một lớp @Configuration (hoặc tương đương xuân cấu hình xml của nó):

@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; 
} 
+0

Đối tượng nào là 'thuộc tính'? – ThreaT

+0

nó là một đối tượng java.util.Properties đơn giản –

12

tôi đã có thể tạo ra một EntityManager với Hibernate và PostgreSQL thuần túy sử dụng mã Java (với cấu hình Spring) như sau:

@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(); 
} 

các cuộc gọi đến LocalContainerEntityManagerFactoryBean.afterPropertiesSet()thiết yếu vì nếu không nhà máy không bao giờ được xây dựng, và sau đó getObject() trả về null và bạn đang theo đuổi sau NullPointerException s cả ngày. > :-(

Sau đó nó làm việc với đoạn mã sau:

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

đâu thực thể của tôi là thế này:

@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 
} 
+1

Thay thế tốt cho Hibernate. – javydreamercsw

3

Với đồng bằng JPA, giả sử rằng bạn có một thực hiện PersistenceProvider (ví dụ Hibernate), bạn có thể sử dụng phương pháp PersistenceProvider#createContainerEntityManagerFactory(PersistenceUnitInfo info, Map map) để khởi động một số EntityManagerFactory mà không cần persistence.xml.

Tuy nhiên, đó là ann oying mà bạn phải thực hiện các giao diện PersistenceUnitInfo, vì vậy bạn nên sử dụng mùa xuân hoặc Hibernate mà cả hai hỗ trợ bootstrapping JPA mà không có một tập tin persistence.xml:

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

Trường hợp PersistenceUnitInfo được thực hiện bởi lớp mùa xuân cụ thể MutablePersistenceUnitInfo.

Kiểm tra this article để có minh chứng tốt về cách bạn có thể đạt được mục tiêu này với Hibernate.

+0

Sử dụng 'MutablePersistenceUnitInfo' không hoạt động như một số phương thức [ném UnsupportedOperationException] (https://github.com/spring-projects/spring-framework/blob/4.3.x/spring-orm/src/main/java/org/ springframework/orm/jpa/persistenceunit/MutablePersistenceUnitInfo.java # L272-L274). Ngoài ra [bài viết] (https://vladmihalcea.com/2015/11/26/how-to-bootstrap-hibernate-without-the-persistence-xml-file/) được đề cập là một chút lỗi thời: 'getPersistenceUnitRootUrl' không thể trả về null nếu không Hibernate không quét classpath (Hibernate 5.2.8). – Brice

+0

Tôi đã sai một chút, bài viết không lỗi thời về vấn đề đó khi mã đang chuyển qua danh sách các thực thể và không sử dụng quét gói. Tuy nhiên đối với quét thực thể tự động, cần phải thực hiện hoặc là 'getPersistenceUnitRootUrl' hoặc 'getJarFileUrls'. Sau này được gieo trong http://stackoverflow.com/a/42372648/48136 – Brice

10

Đây là giải pháp không có Spring. Constants được lấy từ 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(); 

Và khét tiếng 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; 
     } 
    }; 
} 
+3

Điều này đã giúp tôi rất nhiều vì nó giúp tôi tránh sử dụng chi phí sử dụng arquillian trong một số trường hợp thử nghiệm! – cljk

Các vấn đề liên quan