简体   繁体   English

DataIntegrityViolationException保持一对多关系

[英]DataIntegrityViolationException persisting one to many relation

Boot,Jpa and hibernate to persist a one-many relation between venues and events. Boot,Jpa和冬眠使场地和事件之间保持一对多的关系。

The error i'm retrieving is 我正在检索的错误是

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]

I've tried saving the parent(Venue) class first and exclusively but that produces the same error. 我试过先排它地保存parent(Venue)类,但这会产生相同的错误。

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

Event 事件

@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

Controller 控制者

@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);
    }

}
insert into event (id, date, description, media_ref, num_ratings, performer, performer_media, title, total_rating) values (null, ?, ?, ?, ?, ?, ?, ?, ?)

You need to set id to your Event entity. 您需要将ID设置为您的事件实体。 Better use @GeneratedValue annotation with AUTO , like here https://github.com/spring-projects/spring-data-jpa/blob/master/src/main/java/org/springframework/data/jpa/domain/AbstractPersistable.java 最好将@GeneratedValue注释与AUTO ,例如https://github.com/spring-projects/spring-data-jpa/blob/master/src/main/java/org/springframework/data/jpa/domain/AbstractPersistable。爪哇

or use class AbstractPersistable as parent entity. 或使用类AbstractPersistable作为父实体。

Error says that location field of Venue entity is null which cannot be as it is primary key. 错误说地点实体的location字段为空,不能为空,因为它是主键。

You have two options for persisting Event object. 您有两个用于持久保存Event对象的选项。

  1. First persist Venue [Parent] Entity and then Persist as many Event [Child] entities as you want.Set venue field in event entity. 首先保留“场地[父项]”实体,然后持久保留所需的任意“事件[子项]”实体。在事件实体中设置场所字段。 You need to save Parent entity only once. 您只需要保存一次父实体。
  2. If you want to persist both parent and child at once, you can specify cascade = CascadeType.PERSIST in Event Entity and then save child entity. 如果要一次同时保留父项和子项,则可以在事件实体中指定cascade = CascadeType.PERSIST ,然后保存子项。

好的,所以我设法解决了这个问题,事后我不应该盲目地按照教程进行操作,也不知道@MapsId做了什么,所以我删除了它,一切都开始起作用了。这引起了将不胜感激的问题。

You can try this too. 您也可以尝试。

this way you don't need to add parent entry inside child object. 这样,您无需在子对象内添加父项

Remove mappedBy form Venue entity 从表单Venue实体中移除

Then add below code inside the Venue entity before Set<Event> 然后在Set<Event>之前在Venue实体内添加以下代码

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

Remove @JoinColumns and @MapsId from Event entity Event实体中删除@JoinColumns@MapsId

Then you don't need to write 那你就不用写了

event.setVenue(venue);

Hope it helps. 希望能帮助到你。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM