【问题标题】:HashMap not recognizing key, when key is an entity with a list of another entity当键是具有另一个实体列表的实体时,HashMap 无法识别键
【发布时间】:2021-11-08 08:05:39
【问题描述】:

我有一个电子商务类型的应用程序 (Spring Boot) 正在进行中,我正在使用 HashMap 来跟踪购物车中的商品和商品数量。将商品添加到购物车时,hashmap 无法识别相似商品并创建新条目而不是添加到商品计数中。 我知道这在某种程度上与 Jpa 和生成哈希码的方式有关。我尝试了与 POJO 相同的情况(没有 jpa 或任何东西)并且密钥被识别。我尝试重写 equals(Object o) 和 hashCode() 方法,如下所示(忽略有问题的列表),但即使它现在生成相同的哈希码(如下所示)也无济于事。我很高兴能让这个工作,提前谢谢你!

项目:

@Entity
@AllArgsConstructor
@NoArgsConstructor
public class Item extends AbstractPersistable<Long> {

    private String name;

    private Long productNumber;

    private Double price;

    private Double discountPrice;

    private Double discountFactor;

    private Integer stock;

    @Column(length = 10000)
    private String description;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private List<Image> images = new ArrayList<>();

    private Boolean isHidden;

    private Boolean isService;

    @ManyToOne
    private ItemCategory category;

    public Item(String name, Double price, String description, int stock, ItemCategory category) {

        this.name = name;

        this.price = price;

        this.description = description;

        this.stock = stock;

        this.category = category;
    }

    >>getters and setters<<
      
    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        Item item = (Item) o;

        if (name != null ? !name.equals(item.name) : item.name != null) {
            return false;
        }
        if (productNumber != null ? !productNumber.equals(item.productNumber) : item.productNumber != null) {
            return false;
        }
        if (discountPrice != null ? !discountPrice.equals(item.discountPrice) : item.discountPrice != null) {
            return false;
        }
        if (discountFactor != null ? !discountFactor.equals(item.discountFactor) : item.discountFactor != null) {
            return false;
        }
        if (stock != null ? !stock.equals(item.stock) : item.stock != null) {
            return false;
        }
        if (description != null ? !description.equals(item.description) : item.description != null) {
            return false;
        }
        if (isHidden != null ? !isHidden.equals(item.isHidden) : item.isHidden != null) {
            return false;
        }
        if (isService != null ? !isService.equals(item.isService) : item.isService != null) {
            return false;
        }

        return category != null ? category.equals(item.category) : item.category == null;
    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + (productNumber != null ? productNumber.hashCode() : 0);
        result = 31 * result + (discountPrice != null ? discountPrice.hashCode() : 0);
        result = 31 * result + (discountFactor != null ? discountFactor.hashCode() : 0);
        result = 31 * result + (stock != null ? stock.hashCode() : 0);
        result = 31 * result + (description != null ? description.hashCode() : 0);
        result = 31 * result + (isHidden != null ? isHidden.hashCode() : 0);
        result = 31 * result + (isService != null ? isService.hashCode() : 0);
        result = 31 * result + (category != null ? category.hashCode() : 0);
        return result;
    }

图片:

@Entity
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Image extends AbstractPersistable<Long> {

    @Lob
    @Basic(fetch = FetchType.LAZY)
    private byte[] content;

    @ManyToOne
    @JoinColumn(name = "item_id")
    private Item item;

    private Boolean isMainPicture;

    private int ordinal;

}

购物车:

@Component
@AllArgsConstructor
@NoArgsConstructor
@Data
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class ShoppingCart {

    private Map<Item, Long> items = new HashMap<>();

    public void addToCart(Item item) {

        Long itemCount = this.items.getOrDefault(item, 0L) + 1L;

        this.items.put(item, itemCount);

    }

    public void removeFromCart(Item item) {

        if (this.items.get(item) == 1L) {

            this.items.remove(item);
            
            return;
        }

        Long itemCount = this.items.get(item) - 1L;

        this.items.put(item, itemCount);
    }

    public Double getSum() {

        return this.items.keySet().stream()
                .map(item -> (item.getPrice() * this.items.get(item)))
                .reduce(0.0, (currentSum, nextCost) -> currentSum + nextCost);

    }

}

@Controller 中的 viewCart 方法:

@GetMapping("/cart")
public String viewCart(Model model) {
        System.out.println("!!!!!!!!!!!!!!!!!!");
        shoppingCart.getItems().keySet().stream().forEach(key -> System.out.println(key.toString() + "; hashcode = " + key.hashCode()));

        model.addAttribute("items", shoppingCart.getItems());

        return "cart";
    }

viewCart 方法后的控制台,HashMap 中有两个相似的 Item:

!!!!!!!!!!!!!!!!!!
Entity of type mortar.euroshopper.eCommerceApplication.Item with id: 6; hashcode = 34943583
Entity of type mortar.euroshopper.eCommerceApplication.Item with id: 6; hashcode = 34943583

【问题讨论】:

  • 您的 equals/hashcode 对于 JPA 实体存在缺陷。 vladmihalcea.com/… 关于如何正确编写这些内容。
  • 谢谢!工作,代码变得更好看;)
  • 考虑添加评论作为答案,以便它可以被接受并且问题“关闭”并且其他人可以从中受益并轻松理解这可能是类似问题的可能解决方案;)谢谢!

标签: java spring-boot jpa hashmap


【解决方案1】:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-08
    • 2013-08-12
    • 1970-01-01
    • 1970-01-01
    • 2020-10-16
    • 1970-01-01
    相关资源
    最近更新 更多