当前位置: 首页 > 知识库问答 >
问题:

为什么在Spring Boot中多对多关系时不删除DB中的行?

袁泓
2023-03-14

我在Spring Boot应用程序中有多对多关系。我需要创建“收藏夹”功能与用户和广告。用户可以喜欢许多广告,也可以由许多用户喜欢的广告。这就是它们之间的关系:

用户类:

@ManyToMany
    @JoinTable(name = "user_ads",
        joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
        inverseJoinColumns = @JoinColumn(name = "ads_id", referencedColumnName = "id"))
    private Set<Ads> adsFavourites = new HashSet<Ads>();

这是广告类:

@ManyToMany(mappedBy = "adsFavourites")
    private Set<JwtUser> userFavourites = new HashSet<JwtUser>();

这是控制器类:

@DeleteMapping("users/favourites/delete")
    public ResponseEntity<?> deleteUserFavourite(@RequestHeader("Authorization")String token, @RequestParam(required = true) Long userId, @RequestParam(required=true) Long adsId) throws NotFoundException, ForbiddenException {
        jwtUserServiceImplement.deleteFavourite(userId, token, adsId);
        if (jwtUserServiceImplement.isDeleted) {
            return new ResponseEntity<>("OK", HttpStatus.OK);
        } else {
            return new ResponseEntity<>("Not Found", HttpStatus.NOT_FOUND);
        }
    }

这是UserServiceImplementation:

  @Override
    public void deleteFavourite(Long userId, String token, Long adsId) throws ForbiddenException {
        JwtUser jwtUser = jwtRepository.findOneById(userId);
        if (jwtUser != null) {
            for (Ads ads : jwtUser.getAdsFavourites()) {
                if (ads.getId().equals(adsId)) {
                    jwtUser.getAdsFavourites().remove(ads);
                    isDeleted = true;
                    break;
                }
            }
        } else {
            throw new ForbiddenException();
        }
        
    }

要插入收藏夹,用户需要点击广告,该功能运行良好。此外,我可以发送用户收藏的所有广告列表。但是当我想从用户收藏夹中删除一些添加时(用户想从他的收藏夹中删除广告),我做不到。方法执行正常,邮递员返回OK satus,但DB中的行没有删除。只是说我只想从用户列表中删除广告,反之亦然。(所有逻辑都需要从用户的角度完成,而不是从广告角度)。有人能帮我吗?

共有1个答案

山鸿彩
2023-03-14

有几件事。使用调试器。很抱歉听起来有点居高临下,但你应该始终知道你的应用程序在做什么。沿着这些线启用SQL输出。e、 g.<代码>Spring。jpa。show sql=true。

1不要在实体类中实例化Collection。此属性用于查询结果。当您想编写关系时,请创建集合或查询现有集合。删除new HashSet

   private Set<Ads> adsFavourites;

2默认的存储库查询不会实例化关系,或者至少不会实例化多个关系。您需要进行自己的查询来专门读取它们。

@Query("from JwtUser u left join fetch u.adsFavourites where u.id=:id")
JwtUser findByIdJoinAds(@Param("id") Long id);

3在spring数据jpa中,一个实体在查询后被分离,尽管我对此有点模糊。我需要在更改了AdsFavorites集后进行保存。可能是因为许多关系需要一个联接表。

@Override
public void run(String... args) throws Exception {
    write();
    read();
    delete();
    read();
}

@Autowired
JwtUserRepository jwtRepository;
@Autowired
AdsRepository adsRepository;

private void delete() {
    System.out.println("delete");
    JwtUser jwtUser = jwtRepository.findByIdJoinAds(1L);
    for (Ads ads : jwtUser.getAdsFavourites()) {
        if (ads.getId().equals(1L)) {
            jwtUser.getAdsFavourites().remove(ads);
            break;
        }
    }
    jwtRepository.save(jwtUser);
}

private void read() {
    System.out.println("read");
    System.out.println( jwtRepository.findByIdJoinAds(1L) );
}

private void write() {
    System.out.println("write");
    JwtUser user = new JwtUser();
    
    Ads ads1 = new Ads();
    adsRepository.save(ads1);

    Ads ads2 = new Ads();
    adsRepository.save(ads2);
    
    Set<Ads> ads = new HashSet<>();
    ads.add(ads1);
    ads.add(ads2);
    user.setAdsFavourites(ads);
    
    jwtRepository.save(user);
    
}

这给了我:

Hibernate: drop table if exists ads CASCADE 
Hibernate: drop table if exists jwt_user CASCADE 
Hibernate: drop table if exists user_ads CASCADE 
Hibernate: create table ads (id bigint generated by default as identity, primary key (id))
Hibernate: create table jwt_user (id bigint generated by default as identity, primary key (id))
Hibernate: create table user_ads (user_id bigint not null, ads_id bigint not null, primary key (user_id, ads_id))
Hibernate: alter table user_ads add constraint FKjo0u9wqmq7jkp7ovwxg5pebec foreign key (ads_id) references ads
Hibernate: alter table user_ads add constraint FK2tmldht7773rpej1o6nfyfmr foreign key (user_id) references jwt_user
2020-06-20 22:45:37.451  INFO 3048 --- [         task-1] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2020-06-20 22:45:37.457  INFO 3048 --- [         task-1] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2020-06-20 22:45:37.629  INFO 3048 --- [           main] DeferredRepositoryInitializationListener : Spring Data repositories initialized!
2020-06-20 22:45:37.634  INFO 3048 --- [           main] c.m.ManytomanytestApplication            : Started ManytomanytestApplication in 1.704 seconds (JVM running for 2.136)
write
Hibernate: insert into ads (id) values (null)
Hibernate: insert into ads (id) values (null)
Hibernate: insert into jwt_user (id) values (null)
Hibernate: insert into user_ads (user_id, ads_id) values (?, ?)
Hibernate: insert into user_ads (user_id, ads_id) values (?, ?)
read
Hibernate: select jwtuser0_.id as id1_1_0_, ads2_.id as id1_0_1_, adsfavouri1_.user_id as user_id1_2_0__, adsfavouri1_.ads_id as ads_id2_2_0__ from jwt_user jwtuser0_ left outer join user_ads adsfavouri1_ on jwtuser0_.id=adsfavouri1_.user_id left outer join ads ads2_ on adsfavouri1_.ads_id=ads2_.id where jwtuser0_.id=?
JwtUser(id=1, adsFavourites=[Ads(id=1), Ads(id=2)])
delete
Hibernate: select jwtuser0_.id as id1_1_0_, ads2_.id as id1_0_1_, adsfavouri1_.user_id as user_id1_2_0__, adsfavouri1_.ads_id as ads_id2_2_0__ from jwt_user jwtuser0_ left outer join user_ads adsfavouri1_ on jwtuser0_.id=adsfavouri1_.user_id left outer join ads ads2_ on adsfavouri1_.ads_id=ads2_.id where jwtuser0_.id=?
Hibernate: select jwtuser0_.id as id1_1_0_ from jwt_user jwtuser0_ where jwtuser0_.id=?
Hibernate: select adsfavouri0_.user_id as user_id1_2_0_, adsfavouri0_.ads_id as ads_id2_2_0_, ads1_.id as id1_0_1_ from user_ads adsfavouri0_ inner join ads ads1_ on adsfavouri0_.ads_id=ads1_.id where adsfavouri0_.user_id=?
Hibernate: delete from user_ads where user_id=? and ads_id=?
read
Hibernate: select jwtuser0_.id as id1_1_0_, ads2_.id as id1_0_1_, adsfavouri1_.user_id as user_id1_2_0__, adsfavouri1_.ads_id as ads_id2_2_0__ from jwt_user jwtuser0_ left outer join user_ads adsfavouri1_ on jwtuser0_.id=adsfavouri1_.user_id left outer join ads ads2_ on adsfavouri1_.ads_id=ads2_.id where jwtuser0_.id=?
JwtUser(id=1, adsFavourites=[Ads(id=2)])

别忘了:

@Entity
@Data
@EqualsAndHashCode(of = "id")
@ToString(of = "id")
public class Ads {
    ...
}

 类似资料:
  • 问题内容: 我要删除具有多对多关系的一个站点上的表中的一行。我还想删除该关系另一侧的所有相关行。 例如,假设我有以下表格,并且想从中删除一行。我也想从中删除所有相关的行,当然,也删除其中不再需要的任何行。 我知道如何在查询中连接以上表格。但是我看不到如何删除整个关系中的数据。 注意:关系的两端都实现级联删除。因此,例如,从中删除行将删除中的任何相关行。但是显然,这不会传播到表中。 问题答案: 我认

  • 复制和粘贴我前面问题的一些介绍部分。 我在Eclipselink2.3.2中使用JPA2.0,在其中,我在产品和它们的颜色之间建立了多对多的关系。一个产品可以有多种颜色,一种颜色可以与多种产品相关联。这种关系在数据库中由三个表表示。 null 实体类。

  • 我正在使用hibernate多对多的关联。我有3个表(STUDENT,COURSE和STUDENT_COURSE)。在3个表中,2个是主表,1个是提供关系的中间表。当记录从STUDENT中删除时,相应的映射将从Student_Course中删除。我的要求是它甚至应该从课程表中删除记录。考虑以下STUDENT_COURSE条目: 当从学生表中删除101时,上述表中的第一个条目被删除,但课程表中对应于

  • 我的实体: 这就是我的问题,实际上很少有。 问题1: 我删除了一个Cat对象,设置了cascade类型。所有在Cat中拥有的列表中,因此当我删除Cat对象时,UC中带有Cat的所有记录都将被删除,但我得到“已删除的对象将通过级联重新保存”,这是因为我在UC中与用户有另一个关系,用户将UC存储在列表中。当我从UC中删除Cat对象和记录时,我不想删除用户对象,因此在UC中的@ManyToOne上设置c

  • 问题内容: 我有一个Firebase数据库。我有公司和承包商。一个承包商可以为多个公司工作,而一个公司可以有多个承包商。这是直接的多对多关系。我希望能够回答有关公司和承包商的问题: 给定一家公司,他们是当前的承包商。 给承包商一个他们要工作的公司。 在Firebase中构造数据的替代方法有哪些? 问题答案: 自我回答确实是对此进行建模的一种方法。它可能是在关系数据库中建模的最直接等效方法: 承办商

  • 问题内容: 我知道在Elasticsearch中,我们可以在文档之间建立子/父关系。 然后,在建立索引时,我可以传递父代ID,以便将子文档和父文档链接起来: 无论如何,在Elasticsearch中建立多对多关系的模型吗? 数据驻留在具有以下架构的MySQL数据库中: 当前这是我的映射(请原谅数组表示法,我在PHP中使用Elastica与我的Elasticsearch服务器通信): 这种方法的问题