问题的提出:
在开发的过程中,我们会遇到这样的问题,在订单中订单的所属人,这个数据设计时有用户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: 主键数据