jakartaee / persistence

https://jakartaee.github.io/persistence/
Other
196 stars 58 forks source link

Add XML-less config to replace persistence.xml and orm.xml #358

Closed hantsy closed 1 year ago

hantsy commented 2 years ago

Like the @DataSourceDefinition, add annotation config for JPA.

And additionally provide the capability of using CDI beans(eg. like EntityManagerFactorBean role in Spring) to setup JPA.

gavinking commented 1 year ago

@hantsy could you please give an example of what you're proposing here?

hantsy commented 1 year ago

Provide an annotation like this to define a persistence unit without xml file.


@PersistenceUnitDefinition( // @EntityManagerFactoryDefinition
  name = "customerDatabase", // mapped to CDI bean name 
  transactionType="JTA/LOCAL",
  excludedUnlistedClasses=false,
  dataSourceRef="DefaultDS", // the JNDI name from @DataSourceDefinition
  packages= listOf()
  classes= listOf()
  properties=mapOf() // declaring all *jakarta.* prefixed property as const.
  qualifiers=[] // @Qualifier classes
) // repeatable.
@ApplicationScoped
class PersistenceUnits{}

And also provides fluent APIs to build EMF, similar to building Hibernate SessionFactory from Configuration and properties file.

@Dependent
class PersitenceUnitProcducers{

   @Inject // or @Resource
   DataSource dataSource;

   @ApplicationScoped
   @Pooled
   @CustomerDatabase
   EntityManagerFactory  emf(EntityManagerFactory.Builder  builder){
       return builder.name("customerDatabase")
                  .transactionType(JTA)
                  .dataSource(dataSource)
                  .excludedUnlistedClasses(false)
                  .packages()
                  .classes()
                  .properties()
                  .build();
   }
}
  1. Like creating a default DataSource, in a Jakarta EE Container it should create a default persistence unit by default if there is a default DataSource existed, do not depend on the existence of persistence.xml/orm.xml and above annotations.
    @Inject EntityManager em; // connect to the Default DataSource with JTA support in a Jakarta EE container.
    @Inject @Default EntityManager em; 
  2. Use above annotation or fluent API to declare a new custom PersistenceUnit/EntityManagerFactory.
  3. When an EntityManagerFactory bean is available in CDI context, we can inject EntityManager directly via @Inject. Deprecate @PersistenceUnit and @PersistenceContext.

    @Inject @Named("customerDatabase") EntityManager em;
    @Inject @CustomerDatabase EntityManager em;    
    
    // also can inject EMF
    @Inject EntityManagerFactory emf;
gavinking commented 1 year ago

@hantsy I'm not very keen on the annotation. We do have a thing like that which we use for testing Hibernate, so, I mean, there's precedent for it, but in terms of the spec it's unclear who would have the responsibility for discovering such annotations. If it's the EE container, then I don't see the annotation as very useful. Nor am I very keen on us just unilaterally imposing requirements on standalone CDI implementations. So I don't think that works.

On the other hand, a builder API similar to Configuration for bootstrapping an EMF would make plenty of sense. And as you show, this API should be rather easy to define, since its operations probably map pretty much 1-to-1 to elements of the persistence.xml (and, actually, to properties of PersistenceUnitInfo).

But, I dunno, I guess this would be more of a JPA 4.0 thing?

gavinking commented 1 year ago

Note that this issue is essentially a dupe of #149 and #114.

gavinking commented 1 year ago

But, I dunno, I guess this would be more of a JPA 4.0 thing?

Screw it, it's easy enough to do, and there are three different issues requesting it.

Please review #465. (Still need to write some words for the spec, but the basic idea is in the Javadoc.)