首页 > 解决方案 > 实体的 Set contains 方法不起作用

问题描述

我正在尝试将实体与相关的其他实体一起保存。

这是我的实体 在此处输入图像描述

@MappedSuperclass
public abstract class BaseEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    BaseEntity() {

    }

    protected BaseEntity(Long id) {
        this.id = id;
    }

    public Long getId() {
        return id;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        BaseEntity that = (BaseEntity) o;
        return id.equals(that.id);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
}
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "auth_type")
public abstract class BlogUser extends BaseEntity {
    @ManyToOne
    @JoinColumn(name = "user_id", nullable = false, updatable = false)
    private User user;

    @ManyToOne
    @JoinColumn(name = "blog_id", nullable = false, updatable = false)
    private Blog blog;

    BlogUser() {

    }

    protected BlogUser(User user, Blog blog) {
        this.user = user;
        this.blog = blog;
    }

    public User getUser() {
        return user;
    }

    public Blog getBlog() {
        return blog;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof BlogUser)) return false;
        BlogUser blogUser = (BlogUser) o;
        return user.equals(blogUser.getUser()) && blog.equals(blogUser.getBlog());
    }

    @Override
    public int hashCode() {
        return Objects.hash(user, blog);
    }
}
@Entity
@DiscriminatorValue("ADMIN")
public class BlogAdmin extends BlogUser {
    public BlogAdmin(User user, Blog blog) {
        super(user, blog);
    }
}
@Entity
@DiscriminatorValue("INVITED")
public class BlogInvitedUser extends BlogUser {
    public BlogInvitedUser(User user, Blog blog) {
        super(user, blog);
    }
}
@Entity
public class Blog extends BaseEntity {
    
    //fields

    @OneToMany(mappedBy = "blog", cascade = CascadeType.PERSIST)
    private Set<BlogUser> blogUsers = new HashSet<>();

    Blog() {

    }

    public Blog(String name, String introduce) {
        this.name = name;
        this.introduce = introduce;
    }

    //other field's getters

    public Set<BlogUser> getBlogUsers() {
        return blogUsers;
    }

    public void addBlogUser(BlogUser blogUser) {
        if (blogUsers.contains(blogUser)) { // This is not working
            throw new DataIntegrityViolationException("blog's users is duplicated");
        }
        blogUsers.add(blogUser);
    }
}

当使用 BlogUser 子实体的博客用户保存博客实体时,博客的 addBlogUser 方法不起作用!

我知道 Set 通过 hashCode 方法工作。所以,我重写了 BlogUser 实体的 hashCode 和 equals 方法。

但是测试结果很奇怪。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ApplicationConfiguration.class, loader = AnnotationConfigContextLoader.class)
public class BlogUserTest {
    @Autowired
    private UserDao userDao;
    @Autowired
    private BlogDao blogDao;

    @Test
    @Transactional
    public void WhenAddBlogUsers_GivenDifferntTypeSameUserAndBlogAfterPersistBlog_ThrowDataIntegrityViolationException() {
        User user = new User("name", "nick", "email", null);
        userDao.save(user);

        Blog blog = new Blog("test", null);
        BlogUser admin = new BlogAdmin(user, blog);
        blog.addBlogUser(admin);

        blogDao.save(blog);

        System.out.println(blog.getBlogUsers().iterator().next().hashCode() == new BlogInvitedUser(user, blog).hashCode()); // true 
        System.out.println(blog.getBlogUsers().contains(new BlogInvitedUser(user, blog))); // false
    }
}

事实上,在测试时,我知道如果 EntityManager 坚持下去,它就可以工作。

我想知道内部发生了什么。

欢迎任何答案。

标签: javaspringjpa

解决方案


推荐阅读