標籤:
問題的提出:
在開發的過程中,我們會遇到這樣的問題,在訂單中訂單的所屬人,這個資料設計時有使用者id,使用者名稱稱,聯絡資訊等等。這樣做的好處是不用關聯到系統使用者表做資料關聯。
問題是如果使用者表的基礎資訊發生了修改,那麼這個時候,希望修改訂單相應使用者資訊。
解決方案
方案1.
使用資料庫觸發器,這個修改相對簡單,而且不用修改java代碼。
缺點:
有時開發人員可能不能直接接觸資料庫,無法通過此方式實現。
方案2:
使用代碼處理,如果直接在使用者編輯時對業務表進行修改,這樣肯定是不合理的,問題在於這樣每次增加一個業務我們都需要這個使用者代碼進行修改。這樣不滿足封閉開放原則。
現在的解決方案是:
1.在使用者編輯時,發布一個事件。
2.寫監聽器監視這個事件。
3.在資訊修改時調用這個代碼發布事件。
這樣使用者編輯類就不需要做任何更改,發布事件就是了,這個事件可以被系統監聽,也可以不監聽,這樣代碼就
實現瞭解耦。
具體代碼如下:
1.定義事件對象:
public class DataModel {
private String pk="";
private String tableName="";
private String action="";
}
2.定義事件
public class UpdDataEvent extends ApplicationEvent {
/**
*
*/
private static final long serialVersionUID = -656796814656037536L;
public UpdDataEvent(Object source) {
super(source);
}
}
3.定義事件監聽器。
public class UpdateDataListener implements ApplicationListener<UpdDataEvent> {
@Resource(name="jdbcTemplate")
JdbcTemplate jdbcTemplate;
private Map<String,List<String>> sqlMap=new HashMap<String, List<String>>();
@Override
public void onApplicationEvent(UpdDataEvent event) {
DataModel dataModel=(DataModel) event.getSource();
String id=dataModel.getPk();
String tableName=dataModel.getTableName();
List<String> sqlList=sqlMap.get(tableName);
for(String sql:sqlList){
jdbcTemplate.update(sql, id);
}
}
public void setSqlMap(Map<String,List<String>> map){
this.sqlMap=map;
}
}
從外部注入sql map。
這個map鍵是表名,值為List,這個列表對應了sql語句。
oracle下這個sql語句的寫法為:
UPDATE QINGJIA a SET(username) =(SELECT b.fullname FROM sys_user b WHERE b.userid = a.userid) WHERE a.userid=?
必須為一個參數。
4.設定檔的寫法:
<bean id="updateDataListener" class="com.hotent.core.datahandler.UpdateDataListener">
<property name="sqlMap">
<map>
<!--這個為表名,需要和發布事件時保持一直,請統一小寫—>
<entry key="biaoming">
<list>
<!--待更新的sql語句,可以配置多條—>
<value type="java.lang.String">
UPDATE QINGJIA a SET(username) =(SELECT b.fullname FROM sys_user b WHERE b.userid = a.userid) WHERE a.userid=?
</value>
</list>
</entry>
</map>
</property>
</bean>
5.發布事件
public class DataPublishUtil {
/**
* 發布事件。
* @param model
*/
public static void publishData(DataModel model){
AppUtil.publishEvent(new UpdDataEvent(model));
}
/**
* 發布事件。
* @param tableName
* @param pk
*/
public static void publishData(String tableName ,String pk){
DataModel model=new DataModel();
model.setPk(pk);
model.setTableName(tableName);
AppUtil.publishEvent(new UpdDataEvent(model));
}
}
在需要的地方比如使用者編輯時,調用相關方法。
publishData(String tableName ,String pk)
參數說明:
tableName :表名這個需要約定和設定檔中的保持一致。
pk: 主鍵資料
基礎資料修改時修改業務資料的方案實現