2016-04-28 4 views
4

私は本当にここで奇妙な問題を抱えています。リスト内のオブジェクトをリスト内で反復する問題です。 2番目の反復には値を設定する条件がありますが、条件がfalseの場合でもすべての項目に適用されます。 (ハッシュマップのキーとして使用)すべての項目に適用するそれぞれの条件の値を1の代わりに設定する

EventFeedKey:

私は以下のクラスを持っている

public class EventFeedKey { 
    private final int eventId; 
    private final int triggerId; 

    public EventFeedKey(int eventId, int triggerId) { 
     this.eventId = eventId; 
     this.triggerId = triggerId; 
    } 

    @Override 
    public boolean equals(Object object) { 
     if (!(object instanceof EventFeedKey)) { 
      return false; 
     } 

     EventFeedKey otherKey = (EventFeedKey) object; 
     return this.eventId == otherKey.eventId && this.triggerId == otherKey.triggerId; 
    } 

    @Override 
    public int hashCode() { 
     int result = 17; // any prime number 
     result = 31 * result + Integer.valueOf(this.eventId).hashCode(); 
     result = 31 * result + Integer.valueOf(this.triggerId).hashCode(); 
     return result; 
    } 
} 

イベント:

@Entity 
@Table(name = "events") 
public class Event { 
    @Id 
    @Column 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Integer id; 

    @Column(nullable = false) 
    private String title; 

    @ManyToOne(optional = false) 
    @JoinColumn(name = "type_id") 
    private EventType type; 

// Setters and Getters 
} 

イベントタイプ:

@Entity 
@Table(name = "event_types") 
public class EventType { 
    @Id 
    @Column 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Integer id; 

    @Column(nullable = false) 
    private String title; 

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "eventType", cascade = CascadeType.ALL) 
    @JsonManagedReference 
    private List<EventTypeTrigger> triggers = new ArrayList<>(); 

// Setters and Getters 
} 

EventTypeTrigger:

@Entity 
@Table(name = "event_type_triggers") 
public class EventTypeTrigger { 
    @Id 
    @Column 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Integer id; 

    @Column(nullable = false) 
    private String title; 

    @Transient 
    private int count; 

// Setters and Getters 
} 

、次はリストとtriggersFeedからのカウント値で埋めトリガを返す必要があります。

List<Event> eventList = new ArrayList<Event>(); 
    if (eventList != null) { 
     HashMap<EventFeedKey, Integer> triggersFeed = getTriggersWithCounts(); 
     eventList.stream().forEach(event -> { 
      event.getType().getTriggers().stream().forEach(eventTypeTrigger -> { 
       EventFeedKey key = new EventFeedKey(event.getId(), eventTypeTrigger.getId()); 
       eventTypeTrigger.setCount(triggersFeed.get(key) != null ? (Integer) triggersFeed.get(key) : 0); 
      }); 
     }); 
     return eventList; 
    } 

そしてgetTriggersWithCounts()内側:

public HashMap<EventFeedKey, Integer> getTriggersWithCounts() { 
    HashMap<EventFeedKey, Integer> eventTriggers = new HashMap<>(); 
    // event id : 1, trigger id 7 
    eventTriggers.put(new EventFeedKey(1,7), 5); 
    return eventTriggers; 
} 

できますが、私は次のようなデータを持って言う:eventListため

[ 
    { "id":1, "title":"Team A vs Team X", 
     "type":{ 
     "id":3, 
     "title":"Baseball", 
     "triggers":[ 
      { 
       "id":7, 
       "title":"Base Reached", 
       "count":0 
      }, 
      { 
       "id":8, 
       "title":"Out", 
       "count":0 
      } 
     ] 
     } 
    }, 
     { 
     "id":2, "title":"Team A vs Team C", 
     "type":{ 
     "id":3, 
     "title":"Baseball", 
     "triggers":[ 
      { 
       "id":7, 
       "title":"Base Reached", 
       "count":0 
      }, 
      { 
       "id":8, 
       "title":"Out", 
       "count":0 
      } 
     ] 
     } 
    }, 
] 

結果(間違っている)私が得ることメソッドから:

[ 
    { "id":1, "title":"Team A vs Team X", 
     "type":{ 
     "id":3, 
     "title":"Baseball", 
     "triggers":[ 
      { 
       "id":7, 
       "title":"Base Reached", 
       "count":5 
      }, 
      { 
       "id":8, 
       "title":"Out", 
       "count":0 
      } 
     ] 
     } 
    }, 
     { 
     "id":2, "title":"Team A vs Team C", 
     "type":{ 
     "id":3, 
     "title":"Baseball", 
     "triggers":[ 
      { 
       "id":7, 
       "title":"Base Reached", 
       "count":5 
      }, 
      { 
       "id":8, 
       "title":"Out", 
       "count":0 
      } 
     ] 
     } 
    }, 
] 

そして、最も厄介な、私はこの追加した場合:

if (triggersFeed.get(key) != null) { 
    System.out.print(triggersFeed.get(key).toString()); 
} 

を1つだけの結果をプリントアウトします!

だから問題は:なぜid:2のイベントが変更されたのですか?

編集: 私は、問題は今Ebeanに関連すると思う:私はPlayframework内で使用http://ebean-orm.github.io/

+0

どのようにデータを構築していますか?私の気持ちは、両方のEventインスタンスで同じEventTypeへのポインタを持っていて、あるイベントからそれを更新すると、それは他のEventにある同じオブジェクトです –

+0

@ArturBiesiadowskiこれらはデータベースから取得するエンティティです。 1レベル(ネストされたループではありません)ではこのような問題はありません。私はポインタについて考えていたが、デバッグではこれを見ていない。 –

+0

あなたが提供したサンプルを実行しました(各入力イベントを手動で構築しました)。出力はまったく同じです(イベントID = 1の場合はEventTypeTrigger id = 7のみが変更されます)。ほぼ確実に、どちらのイベントでも同じEventTypeTriggerオブジェクトが使用されるという問題があります。 – djmorton

答えて

0

最初に、ヒントのための@ArturBiesiadowskiのおかげで、問題は単純に同じ@Idを持っているのでエンティティインスタンスを参照していたEbeanからの問題であったため、1エンティティの値が設定されていましたが、同じインスタンスであっても、私はそのエンティティを保持していませんでした。リストを取得する前とは異なっていますが、変更を行った後にリストを取得したときにEbeanがgetterで変更されたものを取得したようです。

解決策は単純に別のオブジェクト(DTOのよ​​うなもの)を使用していましたが、私は既にそれを持っていますが、リストを変更してDTOを返すので、リストをDTOに変換してリストを変更しましたこれがうまくいった。

エンティティとDTOの間のマップにhttp://mapstruct.org/を使用しています。私のDTOクラスは、エンティティクラスと同じですが、注釈はありません。

EventDTO:

public class EventDTO { 
    private Integer id; 
    private String title; 
    private EventTypeDTO type; 

// Setters and Getters 
} 

EventTypeDTO:

public class EventTypeDTO { 
    private Integer id; 
    private String title; 
    private List<EventTypeTriggerDTO> triggers = new ArrayList<>(); 

// Setters and Getters 
} 

EventTypeTriggerDTO:今

public class EventTypeTriggerDTO { 
    private Integer id; 
    private String title; 
    private int count; 

// Setters and Getters 
} 

、コードは次のとおりです。

List<Event> eventList = new ArrayList<Event>(); 

    if (eventList != null) { 
     List<EventDTO> eventDTOList = new ArrayList<>(EventMapper.INSTANCE.map(eventList)); 
     HashMap<EventFeedKey, Integer> triggersFeed = getTriggersWithCounts(); 
     eventList.stream().forEach(event -> { 
      event.getType().getTriggers().stream().forEach(eventTypeTrigger -> { 
       EventFeedKey key = new EventFeedKey(event.getId(), eventTypeTrigger.getId()); 
       eventTypeTrigger.setCount(triggersFeed.get(key) != null ? (Integer) triggersFeed.get(key) : 0); 
      }); 
     }); 
     return eventDTOList; 
    } 

マッパーのMapStructのドキュメントに行く必要がありますが、mapstructのMapperを使用したくない場合は、エンティティクラスをDTOクラスにマップするだけです。必要なマッパーを使用してください。この場合、MapStructはうまく動作します。

関連する問題