为每个应用到所有项目而不仅仅是 1 个设置带有条件的值

Setting the value with condition inside for each applying to all items instead of just 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
}

事件类型触发器:

@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
}

并且以下必须 return 列表和触发器填充了来自 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());
}

它只会打印出一个结果!

所以问题是:为什么 id:2 的事件被修改了?

编辑: 我认为现在的问题与 Ebean 相关:我在 Playframework 中使用的 http://ebean-orm.github.io/

首先,感谢@ArturBiesiadowski 的提示,问题只是来自引用实体实例的 Ebean,因为它们具有相同的 @Id ,所以即使我为 1 个实体设置了值,但是当我get entity 我得到了相同的实例,即使我没有保留那个实体,并且在我检索列表之前它们是不同的,但是当我在我完成我的操作后取回列表时,Ebean 似乎得到了修改过的 getter修改.

解决方案是简单地使用另一个对象(如 DTO),我之前已经有了它们,但是我修改了列表,然后 return DTO,我所做的我将列表转换为然后 DTO 修改了列表,这使它起作用了。

我正在使用 http://mapstruct.org/ 在实体和 DTO 之间进行映射,我的 DTO 类 与实体 类 相同,但没有注释。

EventDTO:

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

// Setters and Getters
}

事件类型DTO:

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 的映射器,则想法只是将实体 类 映射到 DTO 类,使用任何映射器您想要,但我确定 MapStruct 在这种情况下运行良好。