Spring + Hibernate使用DB中的值填充holder类

时间:2014-01-15 07:47:32

标签: java spring hibernate java-ee

对于我的网络应用程序,我将从静态数据库表中加载一些详细信息,我计划在容器启动时在单例bean中的HolderClass上加载。我会在任何希望使用静态数据的地方注入这个类。所以基本上我想避免每次从DB

加载静态数据

当前实施:

public Class CountryHolder(){
    List<Country> allCountries;

    public void init(){
       this.countries = loadAllCountries;
    }

    public List<Country> loadAllCountries(){
     // Perform DB select query using JDBC template
    }

上面的实现完全正常,init方法为我的bean加载了Country列表。但是现在我已经迁移到了Hibernate,而Country则是一个Persisten Entity。

休眠:

@Transactional(readOnly ="true")
public List<Country> loadAllCountries(){
   return countryDao.findAll();
}

请注意我已经跳过了我注入dao和jdbc模板的代码。但问题是,因为我在init方法中调用此方法,所以Hibernate抱怨没有找到会话,尽管我已将其声明为readOnly事务。

请告知

2 个答案:

答案 0 :(得分:0)

首先,由于Spring本身不执行持久性,因此无法指定readOnly应该具有什么意义。这个属性只是对提供者的一个提示,行为取决于,在这种情况下,Hibernate。

如果将readOnly指定为true,则当前Hibernate会话中的刷新模式将设置为FlushMode.NEVER,阻止会话提交事务。

此外,将在JDBC Connection上调用setReadOnly(true),这也是底层数据库的提示。如果你的数据库支持它(很可能它),它与FlushMode.NEVER的效果基本相同,但它更强大,因为你甚至无法手动刷新。

如果您发布Hibernate context

,将会更加更有帮助

<强>更新

您对使用ApplicationContextDI

的看法

我的想法是使用一个bean class,它将在spring容器加载时加载。在bean class中你将连接到DB fetch记录并使用你想要使用的地方而不去每次都要DB。

我在我的项目中执行此操作,我在服务器上下文加载时从DB获取一些菜单,并且每次都使用它而不使用roundTriping到DB。

答案 1 :(得分:0)

好的,那么我将发布我在服务器上下文加载时从DB加载Masters所做的工作。

<强> HibernateHelper.java

public final class HibernateHelper 
{
private static SessionFactory sessionFactory;

static 
{
    try {
        // Create the SessionFactory from standard (hibernate.cfg.xml)
        // config file.

        Configuration cfg = new Configuration();

        cfg.configure("hibernate.cfg.xml");

        ServiceRegistry sr = new ServiceRegistryBuilder().applySettings(cfg.getProperties)).buildServiceRegistry();
        SessionFactory tempSessionFactory = cfg.buildSessionFactory(sr);
        sessionFactory = tempSessionFactory;

        } catch (Exception e) {
            throw new ExceptionInInitializerError(e);
        }
}


public Session getSession() 
{
    SessionFactory sessionFactory = getSessionFactory();
        return sessionFactory.openSession();
}

private static SessionFactory getSessionFactory() 
{
    return sessionFactory;
}
}

HibernateHelper类可以通过阅读buildSessionFactory来帮助hibernate.cfg.xml。这个课程有getSession()which return个会话

<强> HibernateHelper_DI.xml

<bean id="Hhelper" class="util.HibernateHelper" />

一个DI xml文件,负责创建HibernateHelper的singalton bean。

<强> MasterHelper.java

public final class MasterHelper implements ApplicationContextAware 
{
       private static getMasterServiceImpl runtimeServiceImpl;
       private static List<Master> masters=null;

       public static List<Master> getMasters()
       {
         if(masters==null)
         {
          loadMasters();
         }
         return masters;
       }

       private static void loadMasters()
       {
          try
          {      
             if(masters==null){      
            masters=runtimeServiceImpl.getMasters();            
            }
          }
          catch(Exception e)
          {
           masters=null;
           throw e;
          }    
       }

        @Override
        public void setApplicationContext(ApplicationContext applicationContext)
                throws BeansException {

            runtimeServiceImpl= (getMasterServiceImpl) applicationContext
                    .getBean("getMasterService");
         }   


}

<强> getMasterService_DI.xml

<bean id="getMasterService" class="service.getMasterServiceImpl" />

一个DI xml文件,负责创建getMasterServiceImpl的singalton bean。

<强> MasterHelper_DI.xml

<bean id="MasterHelper" class="service.MasterHelper" />

一个DI xml文件,负责创建MasterHelper的singalton bean。

通过此配置。 spring知道从哪里读取DI文件。

<强>根context.xml中

<import resource="classpath:DI/*.xml" />

<强>的web.xml

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>

当进行上下文加载时,在web.xmlroot-context.xml的帮助下,spring读取DI文件并相应地生成bean。

当创建HibernateHelper bean时,还会创建sessionfactory并将其保存在静态对象中。以同样的方式创建MasterHelper bean时。

当您第一次在Web应用程序中的任何地方呼叫MasterHelper.getMasters();时,它将转到数据库加载主服务器并分配给静态masters。下次当您致电MasterHelper.getMasters();时,它将检查for null condition to static master

如果您想在bean创建时想要加载母版,那么您可以在MasterHelper中使用更改方法setApplicationContext(),如下所示:

    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {

        runtimeServiceImpl= (getMasterServiceImpl) applicationContext
                .getBean("getMasterService");
                loadMasters(); //IMPOTANT TO CALL HERE ONLY,BCOZ loadMasters NEED BEAN OF       getMasterServiceImpl
     }   

希望这会对你有帮助。

以上所有代码都是手动编写的,因此可能存在一些语法错误,如果找到则请更正