【问题标题】:Hibernate doesn't insert child entities: Hibernate: select nextval ('hibernate_sequence')Hibernate 不插入子实体: Hibernate: select nextval ('hibernate_sequence')
【发布时间】:2020-10-30 13:19:53
【问题描述】:

我有四个班级:AlienAlienAppartmentAlienBuildingAlienBedroom。他们都有ManyToOne 关系:

Alien -> has many AlienBuilding -> has many AlienAppartment -> has many AlienBedroom

我正在尝试通过此控制器插入带有 AlienBuilding 对象的 JSON:

AlienController.java

@CrossOrigin
@RestController
public class AliensController {
    @Autowired
    private AlienBuildingRepository alienBuildingRepository;
    @Autowired
    private AlienRepository alienRepository;
    @Autowired
    private AlienBedroomRepository alienBedroomRepository;
    @Autowired
    private AlienAppartmentRepository alienAppartmentRepository;
    
    ...
 
    @GetMapping("/api/aliens/buildings/insert")
    @Transactional
    public String insertBuilding(
                    @RequestBody AlienBuilding alienBuilding)  {
     alienBuildingRepository.save(alienBuilding);

     return "OK";
    }
}

JSON

{"id":null,"alien":{"id":null,"name":"some alien"},"appartments":[{"id":null,"alienBedrooms":[{"id":null,"description":"cool"}]}]}

但我得到的只是

Hibernate: select nextval ('hibernate_sequence')

在控制台中输出。但是在调试器中,我可以看到 JSON 已映射到 AlienBuilding 对象。

我可以尝试让它通过

插入一些东西
    @GetMapping("/api/aliens/buildings/insert")
    @Transactional
    public String insertBuilding(
                    @RequestBody AlienBuilding alienBuilding)  {
        //alienBuildingRepository.save(alienBuilding);

        alienRepository.save(alienBuilding.getAlien());
        for (AlienAppartment appartment: alienBuilding.getAppartments())  {
            for (AlienBedroom bedroom: appartment.getAlienBedrooms())  {
                alienBedroomRepository.save(bedroom);
                alienBedroomRepository.flush();
            }

            alienAppartmentRepository.save(appartment);
            alienAppartmentRepository.flush();
        }

        alienBuildingRepository.save(alienBuilding);
        alienBuildingRepository.flush();

        return "OK";
    }

我会得到这个输出:

Hibernate: select nextval ('hibernate_sequence')
Hibernate: select nextval ('hibernate_sequence')
Hibernate: insert into aliens (name, id) values (?, ?)
Hibernate: insert into alien_bedrooms (appartment_id, description, id) values (?, ?, ?)
Hibernate: select nextval ('hibernate_sequence')
Hibernate: insert into alien_appartments (building_id, id) values (?, ?)
Hibernate: select nextval ('hibernate_sequence')
Hibernate: insert into alien_buildings (alien_id, id) values (?, ?)

但是alien_appartments 表中的building_id 列以及alien_bedrooms 表中的appartment_id 列将是空的

这些是我的实体:

Alien.java

@Entity
@Table(name = "aliens")
public class Alien  {
    @Id @GeneratedValue
    private int id;

    public Alien()  {}

    @Column
    private String name;

    @OneToMany(mappedBy = "alien", fetch=FetchType.EAGER)
    @JsonIgnore
    private Set<AlienBuilding> buildings;

    /**
     * Getters,setters
     */

AlienAppartment.java


@Entity
@Table(name = "alien_appartments")
public class AlienAppartment {
    @Id
    @GeneratedValue(strategy= GenerationType.AUTO )
    public Long id;

    public AlienAppartment() {
    }

    @OneToMany(mappedBy = "appartment", fetch = FetchType.EAGER,
                        cascade = CascadeType.ALL)
    private Set<AlienBedroom> alienBedrooms;

    @ManyToOne
    @JoinColumn(name = "building_id")
    @JsonIgnore
    private AlienBuilding building;


    /**
     * Getters,setters
     */

AlienBedroom.java

@Entity
@Table(name = "alien_bedrooms")
public class AlienBedroom {
    @Id
    @GeneratedValue(strategy= GenerationType.AUTO )
    private Long id;

    public AlienBedroom()  {}

    @Column
    private String description;

    @ManyToOne
    @JoinColumn(name = "appartment_id")
    @JsonIgnore
   private AlienAppartment appartment;

    /**
     * Getters,setters
     */

AlienBuilding.java

@Entity
@Table(name = "alien_buildings")
public class AlienBuilding {
    @Id
    @GeneratedValue
    public Long id;

    public AlienBuilding() {
    }

    @ManyToOne
    @JoinColumn(name = "alien_id")
    private Alien alien;

    @OneToMany(mappedBy = "building", fetch = FetchType.EAGER)
    private Set<AlienAppartment> appartments;

    /**
     * Getters, setters
     */

存储库

@Repository
public interface AlienAppartmentRepository extends
                JpaRepository<AlienAppartment, Long> {
}

@Repository
public interface AlienBedroomRepository extends JpaRepository<AlienBedroom, Long> {
}

@Repository
@Transactional(value = "transactionManager", propagation = Propagation.REQUIRED)
public interface AlienBuildingRepository
        extends JpaRepository<AlienBuilding, Long> {
}

@Repository
@Transactional(value = "transactionManager", propagation = Propagation.REQUIRED)
public interface AlienRepository extends JpaRepository<Alien, Long> {
}

【问题讨论】:

  • 请提供您使用的hibernate版本、方言和配置。

标签: java spring hibernate spring-mvc jpa


【解决方案1】:

我让它像这样工作:

  1. 我将cascade = CascadeType.ALL 添加到所有内容中:
public class Alien  {
...
    @OneToMany(mappedBy = "alien", fetch=FetchType.EAGER, cascade = CascadeType.ALL)
    @JsonIgnore
    private Set<AlienBuilding> buildings;
...
}
public class AlienAppartment  {
...
@OneToMany(mappedBy = "appartment", fetch = FetchType.EAGER,
                        cascade = CascadeType.ALL)
    private Set<AlienBedroom> alienBedrooms;
...
}

  1. 我确保OneToMany 关系的Many 端具有对One 端的引用。之所以需要它,是因为如果我插入一个建筑物,如果该建筑物引用了外星人,那么外星人也会被插入。因为外星人是One 端,所以它不需要引用包含它的父building 对象。然而,建筑物需要对外星人的引用 - 既要触发插入,又因为外星人的 id 是与建筑物实体关联的表的部分。同样,因为bedroom@OneToManyappartment 的连接的Many 侧(一个公寓有很多卧室,每个卧室只有一个公寓),并且appartment_id 是bedrooms 表的一部分,a卧室必须包含对公寓的引用:
@GetMapping("/api/aliens/buildings/insert")
    @Transactional(value="transactionManager", readOnly=false, propagation =  Propagation.REQUIRED)
    public String insertBuilding(
                    @RequestBody AlienBuilding alienBuilding)  {
        for (AlienAppartment appartment: alienBuilding.getAppartments())  {
            appartment.setBuilding(alienBuilding);

            for (AlienBedroom bedroom: appartment.getAlienBedrooms())  {
                bedroom.setAppartment(appartment);
            }
        }

        alienBuildingRepository.save(alienBuilding);
        alienBuildingRepository.flush();

        return "OK";
    }

还有我发送的 JSON:

{"id":null,"alien":{"id":null,"name":"awesome alien"},"appartments":[{"id":null,"alienBedrooms":[{"id":null,"description":"awesome bedroom"}]}]}

在调试器中的引用方式(断点设置在alienBuildingRepository.save(alienBuilding); 行,就在控制器中插入建筑物之前):

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-16
    • 1970-01-01
    • 2021-12-21
    • 1970-01-01
    • 2022-01-06
    • 1970-01-01
    • 1970-01-01
    • 2021-11-24
    相关资源
    最近更新 更多