Announcement Announcement Module
Collapse
No announcement yet.
Simplest way to inject EntityManager into DAO using only annotation-based DI Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Simplest way to inject EntityManager into DAO using only annotation-based DI

    I'm moving from a project that had been relatively locked into an ancient version of Spring (1.2.7) to one that allows us to use the latest-and-greatest versions of Spring, Hibernate, etc. So far I'm loving annotation-based DI, JPA, etc.! Perhaps it's a little purist, but I'm trying to avoid XML for my app contexts as much as possible given that we abused them as much as used them in the previous project. As a result, I'm trying to use 100% annotation-based DI.

    At this point I have everything generally working with only two XML files, persistence.xml that contains the persistence unit/data source info and a very simple XML app context that contains context:component-scan and tx:annotation-driven. It sounds like with Spring 3.1, I should be able to replace the latter with @AnnotationDrivenTx and AnnotationConfigApplicationContext (or is this possible with Spring 3.0 already? If so, can you provide a pointer to how?).

    In order to get this working I'm using @PersistenceContext to inject the EntityManager into my DAO, and I've created the following simple class that's also in the app context:

    @Named
    public class EntityManagerFactoryBean extends LocalEntityManagerFactoryBean
    {
    public EntityManagerFactoryBean()
    {
    super();
    setPersistenceUnitName("dataSource");
    }
    }

    The other option, as far as I can tell, would have been to add this bean to my XML app context, and that's really my question. The @PersistenceContext annotation accepts a unitName parameter. I tried to remove the bean above from my app context and set the unit name on the annotation, but I get a NoSuchBeanDefinitionException from the PersistenceAnnotationBeanPostProcessor for a bean with the same name as my persistence unit.

    Am I just missing something simple here, or am I already doing this in the simplest way possible by creating the EntityManagerFactoryBean as described above in my app context? That bean just seems superfluous given that I can tell the @PersistenceContext the name of the persistence unit, and fundamentally that's all my EntityManagerFactoryBean is doing.

    Thanks much for any insights here!

  • #2
    Sub-classing your EntityManagerFactory can't be a good idea, unless you really really know what you are doing.

    Code:
    @Repository
    public MyFooDaoImpl implements MyFooDao {
        @PersistenceContext(unitName="persistenceUnit1")
        private EntityManager em;
    
        @Transactional
        public Integer getSomething(Integer valueOne) {
            return em.doSomething(valueOne);
        }
    }

    A quick google givens me some links which explain things better than I can do here.

    http://blog.springsource.com/2006/08...encing-spring/

    Look at the example above, you need a bean org.springframework.orm.jpa.support.PersistenceAnn otationBeanPostProcessor in order to process annotation based @PersistanceContext. http://static.springsource.org/sprin...Processor.html


    You can provide a Persistence Unit Name in your EntityManagerFactory creation. This would be the:
    Code:
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean" />
    Which again can be explained at http://static.springsource.org/sprin...ctoryBean.html checkout the setPersistenceUnitName() in the Abstract base-class it uses.


    I would not call your persistance unit name the same name as a well known other kind of object "dataSource" this seems like a bad choice to make. Call your persistence unit "persistenceUnit1". Note the persistance unit name, is a label for the ORM Factory ("entityManagerFactory" aka EMF) is called, in the context of a larger JEE and app-server there maybe multiple PUs in the one system. Check the documentation for ORM http://static.springsource.org/sprin...rence/orm.html (section 12.6) note in JPA you can specify the dataSource in the persistence.xml but can override it in Spring configuration, see section 12.6. In summary the persistanceUnitName is nothing to do with the underlying JDBC connection source, a persistanceUnitName is a JEE naming concept that is part of the JPA specifications. Think of it like a "bean name or bean id" given to the EMF but because it is part of JPA spec that spring concept works in a JEE that implements JPA but does not use Spring.


    There is no reason at all for you to subclass any class in order to override a setter with spring XML configuration just declare a bean and access the property to set it.


    If you only have a single EntityManagerFactory built for your entire spring project, you do not have to concern yourself with using a persistance unit name. If you use the default bean naming conventions from the blog example (1st URL above) things should be found automatically. If you do indeed require more than 2 PUs then consider getting one working first, then duplicate, then work on the issue of injection qualification via persistance unit names.


    Feel free to hunt the exact version of documentation for your version of spring. Consider trying a cut down example project just to get things working on a smaller scale.
    Last edited by dlmiles; Jul 14th, 2011, 06:37 PM.

    Comment


    • #3
      Thanks for the reply. I was speaking in generic terms in some places. I don't actually call my persistence unit "dataSource". Probably a bad choice to use in my question and example for the exact reason you stated. The persistence unit name doesn't match any well-known bean name and is in fact a beanified version of the DB schema name.

      As for subclassing the entity manager factory, I'm doing that assuming that these two are functionally equivalent (sorry for the formatting, but I'm not sure how to denote a block as code on this forum):

      <bean id="entityManagerFactory" class="org.springframework.org.jpa.LocalEntityMana gerFactoryBean">
      <property name="persistenceUnit" value="myPersistenceUnitName"/>
      </bean>

      and:

      @Named
      public class EntityManagerFactory extends LocalEntityManagerFactoryBean
      {
      public EntityManagerFactory()
      {
      super();
      setPersistenceUnit("myPersistenceUnitName");
      }
      }

      In both bases the bean named entityManagerFactory with the persistence unit named myPersistenceUnitName will be used to populate the @PersistenceContext EntityManager in my DAO. I decided on the latter in pursuit of my goal of having zero XML application context (especially once I can use AnnotationDrivenTx). I'm not aware of any way to use annotation-based dependency injection to create an instance of LocalEntityManagerFactoryBean with the persistence unit property set as above which is why I resorted to the simple subclass, but as you stated, it's far from ideal and definitely not in the spirit of Spring/DI, hence my question here about whether I can avoid that while also avoiding beans defined in XML.

      Thanks again!

      Comment


      • #4
        I'm not aware of any way to use annotation-based dependency injection to create an instance of LocalEntityManagerFactoryBean with the persistence unit property set as above which is why I resorted to the simple subclass, but as you stated, it's far from ideal and definitely not in the spirit of Spring/DI, hence my question here about whether I can avoid that while also avoiding beans defined in XML.
        Why is it any different from the fundimental feature that Spring DI is based on.


        From one of the links I cited:

        http://static.springsource.org/sprin...rence/orm.html (12.6.1.1. LocalEntityManagerFactoryBean)

        Code:
        <beans>
        
           <bean id="myEmf" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
              <property name="persistenceUnitName" value="myPersistenceUnit"/>
           </bean>
        
        </beans>

        You'd do well to read the manual. Not just the JPA section but also the chapters before it. This way you'd understand what is going on better in the above example snippet taken from Spring's own documentation and how it relates to your code example in this thread.

        Maybe check the naming of setPersistenceUnit() against setPersistenceUnitName().


        Not sure I agree with you that using XML is bad and code is better for the things you are configuring. Maybe you can get spring to instate your class code by using @Component("entityManagerFactory") above the 'class' and this would remove the need to put it in XML. But then the next guy along needs to understand where the EMF is coming from in the project, as doing it in code just to configure a user-defined label isn't inherently self-documenting. Sometimes the applicationContext.xml serves as a reference point for the nexy guy along to get an outline for the make up of the project so even if you had your own EMF implementation (and you needed your own class because you override some behaviour) I'd still keep the initated from XML to document what is going on for the next guy.
        Last edited by dlmiles; Jul 15th, 2011, 05:33 PM.

        Comment

        Working...
        X