DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Newsletter
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Implement Hibernate Second-Level Cache With NCache
  • Architectural Miscalculation and Hibernate Problem "Type UUID but Expression Is of Type Bytea"
  • How to Store Text in PostgreSQL: Tips, Tricks, and Traps
  • Simplify Java Persistence Using Quarkus and Hibernate Reactive

Trending

  • Why Spark Executors Leave Cores Idle on YARN: A Packing Model for Executor Sizing
  • Evals in CI: How to Catch Agent Regressions Before Production Does
  • Closing the Drift Loop: An AI Agent That Drafts Terraform Fixes
  • The Window Closes: Why I Switched to Kotlin Before the Codebase Got Too Big

Draft This article hasn't been published, so readers can't see it.

In moderation This article is waiting for review, so readers can't see it yet.

Deleted This article has been deleted, so readers can't see it.

  1. DZone
  2. Data Engineering
  3. Databases
  4. Connecting to Multiple Databases Using Hibernate

Connecting to Multiple Databases Using Hibernate

By 
Taha Siddiqi
·
Mar. 07, 12 · Interview
Post on X (opens in a new tab) Share on LinkedIn (opens in a new tab)
100.5K Views

Join the DZone community Save articles, join the discussion, and download Refcards and Trend Reports with a free account.

Join for free Already a member? Log in

In a recent project, I had a requirement of connecting to multiple databases using hibernate. As tapestry-hibernate module does not provide an out-of-box support, I thought of adding one. https://github.com/tawus/tapestry5

Now that the application is in production, I thought of writing a simple “How to”.

I have cloned the latest stable(5.3.2) tapestry project at

https://github.com/tawus/tapestry5

and have added multiple database support to it.

Single Database

It is almost fully compatible with the previous integration when using a single database except for a few things

1) HibernateConfigurer has changed

public interface HibernateConfigurer
{
   /**
    * Passed the configuration so as to make changes.
    */
   void configure(Configuration configuration);

   /**
    * Factory Id for which this configurer is meant for
    */
   Class<? extends Annotation> getMarker();

   /**
    * Entity package names
    * 
    * @return
    */
   String[] getPackageNames();
}

2) There is no HibernateEntityPackageManager, as the packages can be contributed by adding more HibernateConfigurers with the same Markers.

Multiple databases

For multiple database, a marker has to be used for accessing Session or HibernateSessionManager

@Inject
@XDB
private Session session;

@Inject
@YDB
private HibernateSessionManager sessionManager;

@XDB
@CommitAfter
void myMethod(){

}

Also you have to define a HibernateSessionManager and a Session for the secondary database in the Module class.

@Scope(ScopeConstants.PERTHREAD)
@Marker(DatabaseTwo.class)
public static HibernateSessionManager buildHibernateSessionManagerForFinacle(
    HibernateSessionSource sessionSource,
    PerthreadManager perthreadManager)
{
    HibernateSessionManagerImpl service = new HibernateSessionManagerImpl(sessionSource,
        DatabaseTwo.class);

    perthreadManager.addThreadCleanupListener(service);

    return service;
}

@Marker(DatabaseTwo.class)
public static Session buildSessionForFinacle(
    @Local HibernateSessionManager
        sessionManager,
    PropertyShadowBuilder propertyShadowBuilder)
{
    return propertyShadowBuilder.build(sessionManager, "session", Session.class);
}

Notice an annotation @DatabaseTwo.class. This is a Factory marker and is used to identify a service related to a particular SessionFactory.

@Retention(RetentionPolicy.RUNTIME)
@Target( {ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
@FactoryMarker
@Documented
public @interface DatabaseTwo
{

}

A typical AppModule for two databases will be

public class AppModule
{

    public static void bind(ServiceBinder binder)
    {
        binder.bind(DemoService.class, DemoServiceImpl.class);
    }

    @Contribute(HibernateSessionSource.class)
    public static void configureHibernateSources(OrderedConfiguration<HibernateConfigurer>
        configurers)
    {
        configurers.add("databaseOne", new HibernateConfigurer()
        {
            public void configure(org.hibernate.cfg.Configuration configuration)
            {
                configuration.configure("/databaseOne.xml");
            }

            public Class<? extends Annotation> getMarker()
            {
                return DefaultFactory.class;
            }

            public String[] getPackageNames()
            {
                return new String[] {"org.example.demo.one"};
            }
        });

        configurers.add("databaseTwo", new HibernateConfigurer()
        {
            public void configure(org.hibernate.cfg.Configuration configuration)
            {
                configuration.configure("/databaseTwo.xml");
            }

            public Class<? extends Annotation> getMarker()
            {
                return DatabaseTwo.class;
            }

            public String[] getPackageNames()
            {
                return new String[] {"org.example.demo.two"};
            }
        });
    }

    @Contribute(SymbolProvider.class)
    @ApplicationDefaults
    public static void addSymbols(MappedConfiguration<String, String> configuration)
    {
        configuration.add(HibernateSymbols.DEFAULT_CONFIGURATION, "false");
        configuration.add("tapestry.app-package", "org.example.demo");
    }


    @Scope(ScopeConstants.PERTHREAD)
    @Marker(DatabaseTwo.class)
    public static HibernateSessionManager buildHibernateSessionManagerForFinacle(
        HibernateSessionSource sessionSource,
        PerthreadManager perthreadManager)
    {
        HibernateSessionManagerImpl service = new HibernateSessionManagerImpl(sessionSource,
            DatabaseTwo.class);

        perthreadManager.addThreadCleanupListener(service);

        return service;
    }

    @Marker(DatabaseTwo.class)
    public static Session buildSessionForFinacle(
        @Local HibernateSessionManager
            sessionManager,
        PropertyShadowBuilder propertyShadowBuilder)
    {
        return propertyShadowBuilder.build(sessionManager, "session", Session.class);
    }

}

Injecting into Services

You can inject a session in a service using the marker. As DatabaseOne is being used as the default configuration, in order to inject its Session, you have to annotate it with @DefaultFactory. For DatabaseTwo, you can use @DatabaseTwo annotation.

public class DemoServiceImpl implements DemoService
{
    private Session sessionOne;

    private Session sessionTwo;

    public DemoServiceImpl(
        @DefaultFactory Session sessionOne,
        @DatabaseTwo Session sessionTwo)
    {
        this.sessionOne = sessionOne;
        this.sessionTwo = sessionTwo;
    }

    @SuppressWarnings("unchecked")
    public List<EntityOne> listOnes()
    {
        return sessionOne.createCriteria(EntityOne.class).list();
    }

    @SuppressWarnings("unchecked")
    public List<EntityTwo> listTwos()
    {
        return sessionTwo.createCriteria(EntityTwo.class).list();
    }

    public void save(EntityOne entityOne)
    {
        sessionOne.saveOrUpdate(entityOne);
    }

    public void save(EntityTwo entityTwo)
    {
        sessionTwo.saveOrUpdate(entityTwo);
    }
}


Using @CommitAfter

You can add an advice the same way you used to. The only change is in @CommitAfter. You have to additionally annotate the method with the respective marker.

public interface DemoService
{
    List<EntityOne> listOnes();

    List<EntityTwo> listTwos();

    @CommitAfter
    @DefaultFactory
    void save(EntityOne entityOne);

    @CommitAfter
    @DatabaseTwo
    void save(EntityTwo entityTwo);
}

Here is an example.

 

From http://tawus.wordpress.com/2012/03/03/tapestry-hibernate-multiple-databases/

Database Hibernate

Opinions expressed by DZone contributors are their own.

Related

  • Implement Hibernate Second-Level Cache With NCache
  • Architectural Miscalculation and Hibernate Problem "Type UUID but Expression Is of Type Bytea"
  • How to Store Text in PostgreSQL: Tips, Tricks, and Traps
  • Simplify Java Persistence Using Quarkus and Hibernate Reactive

Partner Resources

×

Comments

Loading comments

The comments didn't load

Please try again in a moment.

Likes

Loading

The next likes didn't load. Please try again.

The likes didn't load

Please try again in a moment.

See who liked this

Log in or join DZone for free to see who liked this article.

Log in Join for free
  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook