Page 3 of 6 FirstFirst 12345 ... LastLast
Results 21 to 30 of 58

Thread: How Common to Spring Manage Beans Created By Hibernate?

  1. #21
    Join Date
    Aug 2004
    Posts
    109

    Default

    And yet there is a better solution in my opnion

    Take a look at AspectJ and Spring integration. It is in its infancy but can be pretty powerfull already.

    Basically, the problem you are having is if your object graph is pretty big you would not want to let Spring create proxies for it (performance issues), on the other hand you would need the business objects to have dependencies injected somehow.

    So the most optimal solution to the problem would be, if you somehow could use the dependent objects inside your business objects (that would be created by Hibernate), but inject dependencies into them say at construction time. This is where AspectJ and Spring integration comes in very handy. Basically you pre-compile your business objects with AspectJ and let Spring inject deps to the aspect itself. At construction time AspectJ's aspect would wire those dependents to your non-proxied BOs. It is pretty neat I must say. Read chapter 6 of the new Spring (1.1) docs for more info on this.

    There are of course disadvantages:

    1. AspectJ's aspects are not dynamic, so if you have multiple deployments of the BOs you would need to pre-compile for each deployment.

    2. AFIKT there is a somewhat signifact problem where perthis, pertarget and percfolw aspects of AspectJ are used.

    HTH
    Thanks,
    Alex.

  2. #22
    Join Date
    Sep 2004
    Posts
    1,086

    Default

    I'm not sure what we need is that each domain object contains the injected session and/or sessionFactory. All you need is a way to map the domain class to the sessionFactory it's coming from - and with spring that mapping shouldn't really be hard to do.

    I can imagine a singleton bean containing Map<Class, SessionFactory> and static getSessionFactory(Class) and getSession(Class) (using SessionFactoryUtils). If you want to, you can fill the map using the Configuration.getClassMappings().

    My guess is this should be enough. If you have one class coming from multiple sessionFactories... Well, you are out of luck anyway. :P

  3. #23
    Join Date
    Sep 2004
    Posts
    1,086

    Default

    Here is some sample code for my mapping bean idea:

    Code:
        <bean name="mySessionUtil" class="dejanp.spring.HibernateSessionUtil">
            <property name="localSessionFactoryBeans">
                <list>
                    <ref bean="&amp;mySessionFactory"/>
                </list>
            </property>
            <property name="mappings">
                <map>
                    <entry key="dejanp.test.TestDomainClass">
                        <ref bean="mySessionFactory"/> 
                    </entry>
                </map>
            </property>
        </bean>
    So, one can use a list of LocalSessionFactoryBeans or a manually filled map or both to init the bean.

    Code:
    package dejanp.spring;
    
    import net.sf.hibernate.Session;
    import net.sf.hibernate.SessionFactory;
    import net.sf.hibernate.cfg.Configuration;
    import net.sf.hibernate.mapping.PersistentClass;
    import org.springframework.orm.hibernate.LocalSessionFactoryBean;
    import org.springframework.orm.hibernate.SessionFactoryUtils;
    
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    
    public class HibernateSessionUtil &#123;
    
        private static Map<String, SessionFactory> map;
    
        public HibernateSessionUtil&#40;&#41; &#123;
            map = new HashMap<String, SessionFactory>&#40;&#41;;
        &#125;
    
        public void setLocalSessionFactoryBeans&#40;List<LocalSessionFactoryBean> localSessionFactoryBeans&#41; &#123;
            for &#40;LocalSessionFactoryBean localSessionFactoryBean &#58; localSessionFactoryBeans&#41; &#123;
                addLocalSessionFactoryBean&#40;localSessionFactoryBean&#41;;
            &#125;
        &#125;
    
        private void addLocalSessionFactoryBean&#40;LocalSessionFactoryBean localSessionFactoryBean&#41; &#123;
            Configuration config = localSessionFactoryBean.getConfiguration&#40;&#41;;
            SessionFactory sessionFactory = &#40;SessionFactory&#41; localSessionFactoryBean.getObject&#40;&#41;;
            Iterator classMappings = config.getClassMappings&#40;&#41;;
            while &#40;classMappings.hasNext&#40;&#41;&#41; &#123;
                PersistentClass persistentClass = &#40;PersistentClass&#41; classMappings.next&#40;&#41;;
                String name = persistentClass.getMappedClass&#40;&#41;.getName&#40;&#41;;
                map.put&#40;name, sessionFactory&#41;;
            &#125;
        &#125;
    
        public void setMappings&#40;Map<String, SessionFactory> map&#41; &#123;
            HibernateSessionUtil.map.putAll&#40;map&#41;;
        &#125;
    
        private static SessionFactory getSessionFactory&#40;Class c&#41; &#123;
            return getSessionFactory&#40;c.getName&#40;&#41;&#41;;
        &#125;
    
        private static SessionFactory getSessionFactory&#40;String name&#41; &#123;
            return map.get&#40;name&#41;;
        &#125;
    
        public static Session getSession&#40;Class c, boolean allowCreate&#41; &#123;
            return SessionFactoryUtils.getSession&#40;getSessionFactory&#40;c&#41;, allowCreate&#41;;
        &#125;
    
    &#125;
    Typical usage would be something like:

    Code:
    public class Order&#123;
        ....
    
        public Collection getSomeOrderItems&#40;...&#41; &#123;
            Session session = HibernateSessionUtil.getSession&#40;Order.class, false&#41;;
            ...
        &#125;
    &#125;

  4. #24
    Join Date
    Aug 2004
    Location
    San Mateo, CA
    Posts
    1,265

    Default

    Another way to do this that is simpler and might perform better: use one of the autowire methods from AutoWireCapableBeanFactory to configure the Hibernate object via Setter Injection, using a dependencyCheck value of false. This way the interceptor should be quite simple. Hibernate would still use new to create objects: Spring would just wire some setters. There would be no need for a prototype definition or any other change in the Spring definitions. The interceptor would need to keep track of which Hibernate-managed classes it wished to wire using Spring.
    Rod Johnson - GM, SpringSource Division, VMware
    http://www.springsource.com
    Spring From the Source

  5. #25
    Join Date
    Aug 2004
    Location
    Hawaii, US
    Posts
    225

    Default

    Ahh... that's a great idea! And, it supports my idea of "Autowire by Prototype". I don't mind declaring one abstract prototype in my context. I could then create an autowire type with semantics of "Autowire physical bean with this abstract prototype bean as an example". I'm not sure that's any better than the other autowire types (by name, by type, etc), but it might be useful.

    Great suggestion, I think I'll switch over to using this method. The Hibernate Interceptor can fallback to the autowire method if it doesn't find a Prototype that matches.

    Thanks!
    Seth

    ps BTW I've been using this Interceptor for a while now, and it works great. It's really simplified our world, allowing us to perform business logic on regular old beans now. So liberating! Now our Facades are simply transaction boundaries, and that's it.

  6. #26
    Join Date
    Aug 2004
    Posts
    218

    Default

    Quote Originally Posted by adepue
    1. What about the client? Do business objects cross the service (facade) boundary, or do you copy everything over into another graph (DTOs?) before sending to the client? If you send the business objects themselves, you would have to rewire all their dependencies on the client side... if you don't send the business objects, then the client is forced to use the facade to access all business logic (good or bad, you decide).
    Also, what if your boundary is over SOAP where your BOs (which have bidirectional references) have to be serialized into XML. This is our scenario and we ended up using DTOs to transfer data back and forth, but find the conversion between the two tedious and to clutter our web service layer somewhat (we continue to use BOs from the application layer down). We've resorted to reflection, recursion and BeanUtils to convert object graphs between DTOs and BOs with good success, but I was wondering if there is a better solution.

    I'm not sure if it's clear to me how Interceptors can help to that end.

    TIA,
    Lou

  7. #27
    Join Date
    Aug 2004
    Location
    San Mateo, CA
    Posts
    1,265

    Default

    Thanks to Seth, who sent me the code, and Oliver, who originally wrote it, I'm in the process of adding this feature in the Spring sandbox. I've done quite a bit of refactoring as I've pulled out a ChainedInterceptorSupport class, as Seth suggested, and also a DependencyInjectionAspectSupport class, which can provide a superclass for an AspectJ/AspectWerkz aspect that does autowiring. I've also added support for autowiring by property (by type or name) as well as the present prototype approach. This will enable much less verbose configuration in simple cases.

    Rgds
    Rod
    Rod Johnson - GM, SpringSource Division, VMware
    http://www.springsource.com
    Spring From the Source

  8. #28
    Join Date
    Aug 2004
    Location
    San Mateo, CA
    Posts
    1,265

    Default

    I've discussed with Andy Jefferson (co-lead of JPOX JDO) adding support in JPOX to enable something like this (though a PersistenceManagerListener mechanism), and I'll discuss it with Patrick Linskey of SolarMetric when I see him at JAOO next week. So hopefully we soon should not merely have Hibernate support for this idiom!
    Rod Johnson - GM, SpringSource Division, VMware
    http://www.springsource.com
    Spring From the Source

  9. #29

    Default

    Quote Originally Posted by Rod Johnson
    I've discussed with Andy Jefferson (co-lead of JPOX JDO) adding support in JPOX to enable something like this
    CVS HEAD for JPOX now provides a PersistenceInterceptor which allows hooks for load, delete and store operations (load not yet fully implemented) on the PersistenceManagerFactory. This will be released in a forthcoming 1.1.0-alpha-3 in about a week.
    -Andy
    DataNucleus - Standardised persistence, multiple datastores

  10. #30

    Default

    Quote Originally Posted by andy
    CVS HEAD for JPOX now provides a PersistenceInterceptor
    This will be updated in the future, as a full JDO 2.0 nears, into "LifecycleListener" - a standard JDO 2.0 facility.
    -Andy
    DataNucleus - Standardised persistence, multiple datastores

Similar Threads

  1. Hibernate Long Session Per Flow?
    By akw in forum Web Flow
    Replies: 21
    Last Post: Dec 12th, 2005, 08:06 PM
  2. Spring container fails with no exception
    By naor in forum Container
    Replies: 9
    Last Post: Oct 1st, 2005, 03:39 PM
  3. Spring code remarks
    By Alarmnummer in forum Architecture
    Replies: 18
    Last Post: Apr 7th, 2005, 07:17 AM
  4. Replies: 14
    Last Post: Feb 21st, 2005, 05:41 PM
  5. Mixing hibernate & spring into single beans
    By ImanRahmati in forum Container
    Replies: 1
    Last Post: Dec 21st, 2004, 07:26 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •