Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring 弹簧座&x2B;JPA&x2B;H2@manytone双向关系。无法存储子实体_Spring_Jpa_One To Many_H2_Many To One - Fatal编程技术网

Spring 弹簧座&x2B;JPA&x2B;H2@manytone双向关系。无法存储子实体

Spring 弹簧座&x2B;JPA&x2B;H2@manytone双向关系。无法存储子实体,spring,jpa,one-to-many,h2,many-to-one,Spring,Jpa,One To Many,H2,Many To One,我在尝试使用JPA存储某些实体时遇到一些问题,情况如下: WebMessageEntity.java @EqualsAndHashCode @Data @Entity(name = "web_message") @NoArgsConstructor @AllArgsConstructor @Builder public class WebMessageEntity{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Getter

我在尝试使用JPA存储某些实体时遇到一些问题,情况如下:

  • WebMessageEntity.java

    @EqualsAndHashCode
    @Data
    @Entity(name = "web_message")
    @NoArgsConstructor
    @AllArgsConstructor
    @Builder
    public class WebMessageEntity{
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Getter
    @Column(name = "WEB_MESSAGE_ID")
    private Long id;
    
    @Getter
    @Setter
    @NotEmpty
    private String hotelTicker;
    
    @Getter
    @Setter
    @NotNull
    @Enumerated(EnumType.STRING)
    private WebMessageColor color;
    
    @Getter
    @Setter
    @NotNull
    @Enumerated(EnumType.STRING)
    @Column(name = "message_type")
    private WebMessageType type;
    
    @Getter
    @Setter
    @NotNull
    @Enumerated(EnumType.STRING)
    private ReservationStep step;
    
    @Getter
    @Setter
    @NotNull
    @Enumerated(EnumType.STRING)
    @Column(name = "message_trigger")
    private WebMessageTrigger trigger;
    
    private int duration;
    
    @Enumerated(EnumType.STRING)
    private WebMessagePosition position;
    
    @Getter
    @Setter
    @NotNull
    private boolean isActive;
    
    @Getter
    @Setter
    @NotNull
    @Convert(converter = LocalDateAttributeConverter.class)
    private LocalDate startDate;
    
    @Getter
    @Setter
    @NotNull
    @Convert(converter = LocalDateAttributeConverter.class)
    private LocalDate endDate;
    
    @Setter
    @OneToMany(mappedBy = "webMessage", cascade = CascadeType.ALL)
    @NotNull
    private List<WebMessageTranslationEntity> translations;
    
    @Getter
    @Setter
    @NotEmpty
    private String userName;
    
    @Getter
    @Setter
    @NotNull
    @Convert(converter = LocalDateTimeAttributeConverter.class)
    private LocalDateTime creationDate;
    
    @Getter
    @Setter
    private String modifiedBy;
    
    @Getter
    @Setter
    @Convert(converter = LocalDateTimeAttributeConverter.class)
    private LocalDateTime modificationDate;
    
    
    //constructors
    //------------------------------------------------------------------------------------------------------
    
    
    
    private WebMessageEntity(String hotelTicker, WebMessageColor color, WebMessageType type, ReservationStep step,
                             WebMessageTrigger trigger, boolean isActive, LocalDate startDate, LocalDate endDate,
                             List<WebMessageTranslationEntity> translations, String userName, LocalDateTime creationDate,
                             String modifiedBy, LocalDateTime modificationDate)
    {
        this.hotelTicker = hotelTicker;
        this.color = color;
        this.type = type;
        this.step = step;
        this.trigger = trigger;
        this.isActive = isActive;
        this.startDate = startDate;
        this.endDate = endDate;
        this.translations = translations;
        this.userName = userName;
        this.creationDate = creationDate;
        this.modifiedBy = modifiedBy;
        this.modificationDate = modificationDate;
    }
    
    private WebMessageEntity(String hotelTicker, WebMessageColor color, WebMessageType type, ReservationStep step,
                            WebMessageTrigger trigger, int duration, WebMessagePosition position, boolean isActive,
                            LocalDate startDate, LocalDate endDate, List<WebMessageTranslationEntity> translations,
                            String userName, LocalDateTime creationDate, String modifiedBy, LocalDateTime modificationDate)
    {
        this.hotelTicker = hotelTicker;
        this.color = color;
        this.type = type;
        this.step = step;
        this.trigger = trigger;
        this.setDuration(duration);
        this.setPosition(position);
        this.isActive = isActive;
        this.startDate = startDate;
        this.endDate = endDate;
        this.translations = translations;
        this.userName = userName;
        this.creationDate = creationDate;
        this.modifiedBy = modifiedBy;
        this.modificationDate = modificationDate;
    }
    
    //GETTERS, SETTERS and some private field verification methods
    
  • @控制器

    @RestController
    @RequestMapping("/api")
    public class WebMessageResource {
    
    
        private final WebMessageService messageService;
    
        @Autowired
        public WebMessageResource(WebMessageService messageService) {
        this.messageService = messageService;
        }
    
    
        @PostMapping("{hotelTicker}/messages")
        public ResponseEntity<?> createMessage(@RequestBody @Valid     WebMessageDTO dto, @PathVariable @NotNull String hotelTicker) {
    
    
            if (verifyHotelTicker(dto, hotelTicker)) {
    
                WebMessageEntity newEntity =         messageService.store(fromWebMessageDTOToEntity(dto));
    
                HttpHeaders headers = new HttpHeaders();
    
                //TODO rebuild URI with exact path to access resource
            headers.setLocation(ControllerLinkBuilder.linkTo(FilterEntity.class).slash(newEntity.getHotelTicker()).slash(newEntity.getId()).toUri());
    
            return new ResponseEntity<>(fromWebMessageEntityToDTO(newEntity), headers, HttpStatus.CREATED);
    
        }
    
        return new ResponseEntity<>("Hotel ticker specified in URI doesn't match with DTO's hotel ticker", HttpStatus.BAD_REQUEST);
    
    }
    
    private boolean verifyHotelTicker(WebMessageDTO dto, String hotelTicker) {
        return hotelTicker.equals(dto.getHotelTicker());
    }
    
    private List<WebMessageTranslationEntity> fromTranslationDTOsToEntities(List<WebMessageTranslationDTO> translationDTOs) {
    
        return translationDTOs
                .stream()
                .map(translation -> WebMessageTranslationEntity
                        .builder()
                        .content(translation.getContent())
                        .locale(translation.getLocale())
                        .build())
                    .collect(toList());
    
        }
    
        private WebMessageEntity fromWebMessageDTOToEntity(WebMessageDTO webMessageDTOs) {
    
            return WebMessageEntity
                    .builder()
                    .hotelTicker(webMessageDTOs.getHotelTicker())
                    .color(webMessageDTOs.getColor())
                    .type(webMessageDTOs.getType())
                    .step(webMessageDTOs.getStep())
                    .trigger(webMessageDTOs.getTrigger())
                    .duration(webMessageDTOs.getDuration())
                    .position(webMessageDTOs.getPosition())
                    .isActive(webMessageDTOs.getIsActive())
                    .startDate(webMessageDTOs.getStartDate())
                    .endDate(webMessageDTOs.getEndDate())
                    .userName(webMessageDTOs.getUserName())
                    .creationDate(webMessageDTOs.getCreationDate())
                    .modifiedBy(webMessageDTOs.getModifiedBy())
                    .modificationDate(webMessageDTOs.getModificationDate())
                    .translations(this.fromTranslationDTOsToEntities(webMessageDTOs.getTransla    tions()))
                    .build();
    }
    
    private WebMessageDTO fromWebMessageEntityToDTO(WebMessageEntity webMessageEntity) {
    
        return WebMessageDTO
                .builder()
                .id(webMessageEntity.getId())
                .hotelTicker(webMessageEntity.getHotelTicker())
                .color(webMessageEntity.getColor())
                .type(webMessageEntity.getType())
                .step(webMessageEntity.getStep())
                .trigger(webMessageEntity.getTrigger())
                .duration(webMessageEntity.getDuration())
                .position(webMessageEntity.getPosition())
                .isActive(webMessageEntity.isActive())
                .startDate(webMessageEntity.getStartDate())
                .endDate(webMessageEntity.getEndDate())
                .userName(webMessageEntity.getUserName())
                .creationDate(webMessageEntity.getCreationDate())
                .modifiedBy(webMessageEntity.getModifiedBy())
                .modificationDate(webMessageEntity.getModificationDate())
                .translations(this.fromTranslationEntitiesToDTO(webMessageEntity.getTranslations()))
                .build();
    }
    
    private List<WebMessageTranslationDTO> fromTranslationEntitiesToDTO(List<WebMessageTranslationEntity> translationEntities) {
    
        return translationEntities
                .stream()
                .map(translation -> WebMessageTranslationDTO
                        .builder()
                        //.id(translation.getId())
                        .content(translation.getContent())
                        .locale(translation.getLocale())
                        .build())
                .collect(toList());
    }
    
    
    }
    
  • 表创建YAML文件

    - changeSet:
      id: '008-1'
      author: arnau
      comment: 'create table web_message'
      preConditions:
        - onFail: MARK_RAN
        - onFailMessage: 'Table already exists, must be production environment...'
        - not:
          - tableExists:
              tableName: web_message
      changes:
      - createTable:
          tableName: web_message
          columns:
          - column:
              name: WEB_MESSAGE_ID
              type: NUMBER
              autoIncrement: true
              constraints:
                primaryKey: true
                nullable: false
          - column:
              name: hotel_ticker
              type: VARCHAR(155)
              constraints:
                nullable: false
          - column:
              name: color
              type: VARCHAR(255)
              constraints:
                nullable: false
          - column:
              name: message_type
              type: VARCHAR(255)
              constraints:
                nullable: false
          - column:
              name: step
              type: VARCHAR(255)
              constraints:
                nullable: false
          - column:
              name: message_trigger
              type: VARCHAR(255)
              constraints:
                nullable: false
          - column:
              name: duration
              type: NUMBER
              constraints:
                nullable: true
          - column:
              name: position
              type: VARCHAR(255)
              constraints:
                nullable: true
          - column:
              name: is_active
              type: BOOLEAN(1)
              constraints:
                nullable: false
          - column:
              name: start_date
              type: DATE
              constraints:
                nullable: false
          - column:
              name: end_date
              type: DATE
              constraints:
                nullable: false
          - column:
              name: user_name
              type: VARCHAR(255)
              constraints:
                nullable: false
          - column:
              name: creation_date
              type: TIMESTAMP
              constraints:
                nullable: false
          - column:
              name: modified_by
              type: VARCHAR(255)
              constraints:
                nullable: true
          - column:
              name: modification_date
              type: TIMESTAMP
              constraints:
                nullable: true
    
    
    - changeSet:
          id: '008-2'
          author: arnau
          comment: 'create table web_message_translation'
          preConditions:
            - onFail: MARK_RAN
            - onFailMessage: 'Table already exists, must be production environment...'
            - not:
              - tableExists:
                  tableName: web_message_translation
          changes:
          - createTable:
              tableName: web_message_translation
              columns:
              - column:
                  name: MESSAGE_TRANSLATION_ID
                  type: NUMBER
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: locale
                  type: VARCHAR(2)
                  constraints:
                    unique: true
                    nullable: false
              - column:
                  name: content
                  type: VARCHAR(255)
                  constraints:
                    nullable: false
              - column:
                  name: message_id
                  type: CHAR(22)
                  constraints:
                    nullable: false
                    references: web_message(WEB_MESSAGE_ID)
                    foreignKeyName:     fk_web_message_translation__web_message
      - changeSet:
          id: '008-3'
          author: arnau
          comment: 'Add unique constraint by locale and web_message_id'
          changes:
          - addUniqueconstraint:
            tableName: web_message_translation
            columnNames: locale, message_id
            constraintName: uc_locale__message_id
    
  • 问题是,当我尝试存储这些实体时,JPA尝试将实体
    webMessageTranslationEntity
    存储在
    message\u id
    列中,该列的值为NULL,显然,DB会拒绝该项,因为该字段被设置为非NULL

    如何使用此必备项存储这些实体?

    @NotNull
    
    @NotNull
    private List<WebMessageTranslationEntity> translations;
    
    私人名单翻译;
    这会将外键上的约束设置为不为null

  • 保留约束并注入持久化的WebMessageEntity
  • 保留约束并注入一个非持久化WebMessageEntity,但需要将WebMessageEntity端的级联设置为持久化(或全部)
  • 通过删除@NotNull更改约束
  • @NotNull
    私人名单翻译;
    
    这会将外键上的约束设置为不为null

  • 保留约束并注入持久化的WebMessageEntity
  • 保留约束并注入一个非持久化WebMessageEntity,但需要将WebMessageEntity端的级联设置为持久化(或全部)
  • 通过删除@NotNull更改约束

  • 更改约束不是一个选项,因此我尝试在WebMessageTranslation entit的WebMessageEntity属性中添加一个CascadeType.ALL,如下所示:
    @manytone(cascade=CascadeType.ALL)@JoinColumn(name=“MESSAGE\u ID”)私有WebMessageEntity webMessage但是问题仍然存在,所以最后我必须单独持久化这些实体,首先持久化WebMessageEntity,然后持久化WebMessageTranslations。但我认为这必须是一种更干净的方式。我认为它已经解决了,但如果我找到更好的方法,我会把它贴在这里。Thank's a lot@amerqarabsat级联定义了子实体上操作的级联,因此如果您有一个对B的引用的a,并且您希望在持久化a时持久化引用的B,那么您将在a内部根据B引用的关系定义级联,因此,在您的cane中,它应该在OneToMany而不是ManyTone中更改约束不是一个选项,因此我尝试添加一个CascadeType.ALL在WebMessageTranslation entit的WebMessageEntity属性中,如下所示:
    @manyTone(cascade=CascadeType.ALL)@JoinColumn(name=“MESSAGE\u ID”)私有WebMessageEntity webMessage但是问题仍然存在,所以最后我必须单独持久化这些实体,首先持久化WebMessageEntity,然后持久化WebMessageTranslations。但我认为这必须是一种更干净的方式。我认为它已经解决了,但如果我找到更好的方法,我会把它贴在这里。Thank's a lot@amerqarabsat级联定义了子实体上操作的级联,因此,如果您有一个对B的引用的a,并且您希望在持久化a时持久化引用的B,那么您将在a内部根据B引用的关系定义级联,因此在您的cane中,它应该在一个域中,而不是在多个域中
    
    - changeSet:
      id: '008-1'
      author: arnau
      comment: 'create table web_message'
      preConditions:
        - onFail: MARK_RAN
        - onFailMessage: 'Table already exists, must be production environment...'
        - not:
          - tableExists:
              tableName: web_message
      changes:
      - createTable:
          tableName: web_message
          columns:
          - column:
              name: WEB_MESSAGE_ID
              type: NUMBER
              autoIncrement: true
              constraints:
                primaryKey: true
                nullable: false
          - column:
              name: hotel_ticker
              type: VARCHAR(155)
              constraints:
                nullable: false
          - column:
              name: color
              type: VARCHAR(255)
              constraints:
                nullable: false
          - column:
              name: message_type
              type: VARCHAR(255)
              constraints:
                nullable: false
          - column:
              name: step
              type: VARCHAR(255)
              constraints:
                nullable: false
          - column:
              name: message_trigger
              type: VARCHAR(255)
              constraints:
                nullable: false
          - column:
              name: duration
              type: NUMBER
              constraints:
                nullable: true
          - column:
              name: position
              type: VARCHAR(255)
              constraints:
                nullable: true
          - column:
              name: is_active
              type: BOOLEAN(1)
              constraints:
                nullable: false
          - column:
              name: start_date
              type: DATE
              constraints:
                nullable: false
          - column:
              name: end_date
              type: DATE
              constraints:
                nullable: false
          - column:
              name: user_name
              type: VARCHAR(255)
              constraints:
                nullable: false
          - column:
              name: creation_date
              type: TIMESTAMP
              constraints:
                nullable: false
          - column:
              name: modified_by
              type: VARCHAR(255)
              constraints:
                nullable: true
          - column:
              name: modification_date
              type: TIMESTAMP
              constraints:
                nullable: true
    
    
    - changeSet:
          id: '008-2'
          author: arnau
          comment: 'create table web_message_translation'
          preConditions:
            - onFail: MARK_RAN
            - onFailMessage: 'Table already exists, must be production environment...'
            - not:
              - tableExists:
                  tableName: web_message_translation
          changes:
          - createTable:
              tableName: web_message_translation
              columns:
              - column:
                  name: MESSAGE_TRANSLATION_ID
                  type: NUMBER
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: locale
                  type: VARCHAR(2)
                  constraints:
                    unique: true
                    nullable: false
              - column:
                  name: content
                  type: VARCHAR(255)
                  constraints:
                    nullable: false
              - column:
                  name: message_id
                  type: CHAR(22)
                  constraints:
                    nullable: false
                    references: web_message(WEB_MESSAGE_ID)
                    foreignKeyName:     fk_web_message_translation__web_message
      - changeSet:
          id: '008-3'
          author: arnau
          comment: 'Add unique constraint by locale and web_message_id'
          changes:
          - addUniqueconstraint:
            tableName: web_message_translation
            columnNames: locale, message_id
            constraintName: uc_locale__message_id
    
    @NotNull
    private List<WebMessageTranslationEntity> translations;