DataIntegrityViolationException持久化一对多关系

问题描述 投票:0回答:4

Boot,Jpa和hibernate在场地和事件之间保持一对多的关系。

我正在检索的错误是

org.h2.jdbc.JdbcSQLException: NULL not allowed for column "VENUE_LOCATION"; SQL statement:
insert into event (id, date, description, media_ref, num_ratings, performer, performer_media, title, total_rating) values (null, ?, ?, ?, ?, ?, ?, ?, ?) [23502-192]

我已经尝试首先保存父(Venue)类,但是它会产生相同的错误。

地点

public class Venue
{
    @Id
    private String name;

    @Id
    private String location;

    @OneToOne(mappedBy = "venue",cascade = CascadeType.ALL)
    @JoinColumn(name="id")
    private VenueUser venueUser;

    private String mediaRef;

    private int rating;

    @OneToMany(fetch=FetchType.LAZY,mappedBy = "venue",cascade = CascadeType.ALL)
    private Set<Event> events;
    //Constructors getters and setters below

事件

@Entity
public class Event 
{
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private long id;

private String title;
private String description;
private String performer;
private String[] performerMedia;
private Calendar[] date;

@Transient
private double avgRating;

private int numRatings;
private int totalRating;

private String mediaRef;

@MapsId("name")
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumns({
        @JoinColumn(name="Venue_name",referencedColumnName = "name"),
        @JoinColumn(name="venue_location",referencedColumnName = "location")
})
private Venue venue;
 //Constructors getters and setters below

调节器

@RequestMapping(value = "/event",method=RequestMethod.POST)
public ResponseEntity addEvent(@RequestBody Event event)
{
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    String name = auth.getName(); //get logged in username
    Venue venue = userVenueRepository.findByEmail(name).getVenue();

    event.setVenue(venue);
    venue.addEvent(event);

    if(eventRepository.saveAndFlush(event).equals(event)&&venueRepository.saveAndFlush(venue).equals(venue))
    {
        return new ResponseEntity(HttpStatus.CREATED);
    }
    else
    {
        return new ResponseEntity(HttpStatus.CONFLICT);
    }

}
java hibernate jpa spring-boot one-to-many
4个回答
0
投票
insert into event (id, date, description, media_ref, num_ratings, performer, performer_media, title, total_rating) values (null, ?, ?, ?, ?, ?, ?, ?, ?)

您需要将id设置为Event实体。更好地使用@GeneratedValue注释与AUTO,像这里https://github.com/spring-projects/spring-data-jpa/blob/master/src/main/java/org/springframework/data/jpa/domain/AbstractPersistable.java

或使用AbstractPersistable类作为父实体。


0
投票

错误说Venue实体的location字段为null,因为它不是主键。

您有两个持久化Event对象的选项。

  1. 首先保留Venue [Parent] Entity,然后根据需要保留尽可能多的Event [Child]实体。在事件实体中设置场地字段。您只需要保存一次父实体。
  2. 如果要同时保留父级和子级,可以在Event Entity中指定cascade = CascadeType.PERSIST,然后保存子实体。

0
投票

好的,所以我设法修复了这个并且事后我不应该盲目地遵循教程,我不确定@MapsId做了什么所以我删除它并且一切都开始工作。如果有人能解释@MapsId做什么以及为什么它引起了一些值得赞赏的问题。


0
投票

你也可以尝试一下。

这样您就不需要在子对象中添加父条目。

删除mappedBy形式的Venue实体

然后在Venue之前在Set<Event>实体中添加以下代码

@JoinColumns({
        @JoinColumn(name="Venue_name",referencedColumnName = "name"),
        @JoinColumn(name="venue_location",referencedColumnName = "location")
})

@JoinColumns实体中删除@MapsIdEvent

那你就不需要写了

event.setVenue(venue);

希望能帮助到你。

© www.soinside.com 2019 - 2024. All rights reserved.