加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – 如何在ibatis 2.3.4中有效地映射复杂的集合属性

发布时间:2020-12-15 02:25:00 所属栏目:Java 来源:网络整理
导读:我有一个域对象,表示数据库表之间的1:n关系. public class ObservationWithData { private Observation observation; private MapInteger,ElementValue elementValues; // accessor methods... } Observation和ElementValue都包含 private int datetimeId;
我有一个域对象,表示数据库表之间的1:n关系.

public class ObservationWithData {
   private Observation observation;
   private Map<Integer,ElementValue> elementValues;
   // accessor methods
... }

Observation和ElementValue都包含

private int datetimeId;
   private int stationId;
   // accessor methods
   ...

我有一个连接两个表的选择查询.我想使用resultMap将ElementValues与基于datetimeId和stationId的Observations分组,如本(非工作)示例所示.

<resultMap id="observationWithDataMap" class="ObservationWithData" 
           groupBy="observation.datetimeId,observation.stationId">
  <result property="observation" resultMap="ObservationSql.observationMap" />
  <result property="elementValues" resultMap="ElementSql.elementValueMap"/>
</resultMap>

这有两个问题.首先,groupBy标记不允许嵌套语法,第二个iBATIS要求分组属性是Java Collections API的一部分,而Map不符合该标准.

我可以通过添加datetimeId和stationId访问器来解决第一个问题,第二个项目可以通过创建要写入的集合来解决,然后在数据提取后将所有项目添加到地图中.

<resultMap id="observationWithDataMap" class="ObservationWithData" 
           groupBy="datetimeId,stationId">
  <result property="stationId" column="station_id" />
  <result property="datetimeId" column="datetime_id" />
  <result property="observation" resultMap="ObservationSql.observationMap" />
  <result property="elementValueCollection" resultMap="ElementSql.elementValueMap"/>
</resultMap>

public class ObservationWithData {
   private Observation observation;
   private Map<Integer,ElementValue> elementValues;
   // this collection is used for database retrieval only; do not add to it
   private Collection<ElementValue> elementValueCollection;

   public void setStationId(int id) { }
   public int getStationId() {
   return observation==null?0:observation.getStationId();
   }
   public void setDatetimeId(int id) { }
   public int getDatetimeId() {
   return observation==null?0:observation.getDatetimeId();
   }

   public Map<Integer,ElementValue> getElementValues() {
   if (elementValues.size()==0 && elementValueCollection.size()>0) {
       for (ElementValue val : elementValueCollection) {
           elementValues.put(val.getElementId(),val);
       }
       elementValueCollection.clear();
   }
   return elementValues;
   }

   public Collection<ElementValue> getElementValueCollection() {
   if (elementValueCollection.size()==0 && elementValues.size()>0) {
       elementValueCollection.addAll(elementValues.values());
       elementValues.clear();
   }
   return elementValueCollection;
   }
   ... }

不过,我对这个解决方案不是很满意,因为现在有很多公共方法我不希望人们在他们的代码中使用. id setter是noops,因为这些id在观察中被设置.我可以使用ObservationWithData扩展Observation,但是我设计这个类有利于每个Effective Java的继承组合.我也可以不同地同步地图和集合,但我的想法是我会让iBATIS填充集合,然后当访问地图时,我会将所有值移入其中,只保留一个引用.

有人可以推荐更优雅的解决方案吗?

编辑:

我最终提取了一个服务层来处理这个问题.服务层通过DAO而不是一个进行两次数据库调用;第一个检索所有Observations,第二个检索所有ElementValues.它从这些集合构造ObservationWithData对象.它还会限制请求,因为这是一个大型数据集.

这是一个有点笨拙和低效,因为我“手动”构建对象.但是,由于这是“隐藏”在服务层中,我觉得它对API用户的干扰较小,他们可以使用整洁的域对象.

解决方法

您是否尝试编写DAO以便这是一个两阶段的过程,首先获取ObservationWithData对象然后用elementValues填充它们?它不会扩展到大量的行,但取决于你需要获取它可能会使它在外面变得更干净.

另一种选择是通过将结果映射到具有getter和setter的包私有对象,然后将它们作为不带有setter的不同类返回给调用者来从数据库中获取数据.不确定这是否会有所帮助,我认为它甚至可能会给解决方案带来更多麻烦.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读