cuiyi's blog(崔毅 crazycy)

记录点滴 鉴往事之得失 以资于发展
数据加载中……

Spring-系统启动时初始化数据库的数据/系统启动时操作数据库

需求:在系统启动的时候把数据库的数据进行重置(或者插入数据,或者取出一系列的数据缓存起来)

摸索:SBean可以IoC注入需要的资源比如DataSource;

Spring Bean Config
<bean id="idPoolsInitilizedProcessor" class="utils.IDPoolsInitilizedListener" scope="singleton" >
        <property name="datasource" ref="dataDS"/>
 </bean>

Spring Bean Code
public class JcIDPoolsInitilizedListener {
    private DataSource datasource = null
  
  public JcIDPoolsInitilizedBean() {
    System.out.println("%%%%%%%%%%%%%%");    
    try {
      //initilize msgid
      String refName = CxcConstants.REFCOUNTER_MSGID; 
      String sql = "update refcounter set nextnumber=(select max(msgid)+1 from msg) where refcounterid=?";
      update(sql, new Object[]{refName}); 
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }
    private int update(String anSql, Object[] args) throws Exception {
      int affactRows = 0;
      Connection con = null;
      PreparedStatement stmt = null;
      try {
        con = datasource.getConnection();
        stmt = con.prepareStatement(anSql);
        setSQLParams(stmt, args);
        affactRows = stmt.executeUpdate();
        return affactRows;
      } finally {
        try
          if (null != stmt) {
            stmt.close();
          }
          if (null != con) {
            con.close();
          }
        } catch (Exception ex) {
          ex.printStackTrace();
        }
      }
    }
    
    private void setSQLParams(PreparedStatement stmt, Object[] args) throws Exception {
      if (null != args && 0 < args.length) {
        for (int i = 0, n = args.length; i < n; i++) {
          stmt.setObject(i + 1, args[i]);
        }
      }
    }

    public DataSource getDatasource() {
      return datasource;
    }

    public void setDatasource(DataSource datasource) {
      this.datasource = datasource;
    }
}

结果:程序启动的时候会抛出NullPointException,因为datasource并没有初始化好。

摸索:Spring的事件机制:实现ApplicationListener,在onApplicationEvent的方法进行数据初始化操作,只要容器启动,就会执行这里的代码。

public class JcIDPoolsInitilizedListener implements ApplicationListener {
  
  private DataSource datasource = null
  
  public void onApplicationEvent(ApplicationEvent argo) {
    //todo: code is same as previous 
  }
    
  //todo: all the other part is same as previous
}

成功。

然后的然后呢?会发现程序中这个初始化被多次调用。
为什么呢? 原因是Listener定义不到位。
为什么呢? 只要是ApplicationEvent都会触发,默认的事件是org.springframework.security.access.event.PublicInvocationEvent,肯定触发的。

怎么办呢?
好吧,既然是Listener,总得告诉它Listen什么Event吧。
第一 定义Listener
public class JcIDPoolsInitilizedListener implements ApplicationListener {
  
  private DataSource datasource = null
  
  public void onApplicationEvent(ApplicationEvent argo) {
     if (argo instanceof IDPoolsInitilizedEvent) {
        //todo: code is same as previous 
     }
   
     //todo: all the other part is same as previous
}

第二 定义Event
public class IDPoolsInitilizedEvent extends ApplicationEvent{
  private static final long serialVersionUID = 646140097162842368L;
  
  public IDPoolsInitilizedEvent(Object source){
     super(source);
  }
}

第三 定义Event抛出点

public class IDPoolsInitilizedBean implements ApplicationContextAware{
  private ApplicationContext applicationContext;
  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    this.applicationContext = applicationContext;
    IDPoolsInitilizedEvent event = new IDPoolsInitilizedEvent("IDPoolsInitilized");
    this.applicationContext.publishEvent(event);
  }
}

第四 定义配置文件
<bean id="idPoolsInitilizedListenerProcessor" class="utils.IDPoolsInitilizedListenerBean"
        scope
="singleton" >
        <property name="datasource" ref="dataDS"/>
    </bean>
    <bean id="idPoolsInitilizedProcessor" class="utils.IDPoolsInitilizedBean"
        scope
="singleton" />

posted on 2013-03-17 19:55 crazycy 阅读(5753) 评论(0)  编辑  收藏 所属分类: JavaEE技术


只有注册用户登录后才能发表评论。


网站导航: