Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.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
SpringBoot 2.1.4.RELEASE应用程序中的SQL错误:23503,SQLState:23503_Spring_Jpa_Spring Data Jpa_Spring Data - Fatal编程技术网

SpringBoot 2.1.4.RELEASE应用程序中的SQL错误:23503,SQLState:23503

SpringBoot 2.1.4.RELEASE应用程序中的SQL错误:23503,SQLState:23503,spring,jpa,spring-data-jpa,spring-data,Spring,Jpa,Spring Data Jpa,Spring Data,我有一个SpringBoot 2.1.4.RELEASE RESTful Web服务应用程序,使用Spring初始值设定项、嵌入式Tomcat、Thymeleaf模板引擎,并将包作为可执行JAR文件 我有这门课: @Entity @Table(name="t_menu_alert_notification") public class MenuAlertNotification implements Serializable { /** * */ priv

我有一个SpringBoot 2.1.4.RELEASE RESTful Web服务应用程序,使用Spring初始值设定项、嵌入式Tomcat、Thymeleaf模板引擎,并将包作为可执行JAR文件

我有这门课:

@Entity
@Table(name="t_menu_alert_notification")
public class MenuAlertNotification implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;


    public MenuAlertNotification() {
        super();
    }


    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @JsonProperty("id")
    private Long id;    

    @JsonProperty("subject")
    protected String subject;

    @JsonIgnore
    protected Integer trend;

    @JsonIgnore
    protected String message;

    @JsonProperty("notified")
    private Boolean notified;

    @Column(name = "is_read")
    protected Boolean read;

    @JsonProperty("creationDate")
    @Convert(converter = LocalDateTimeAttributeConverter.class)
    protected LocalDateTime creationDate;


    @ManyToOne(fetch = FetchType.EAGER)
        @JoinColumn(name = "menu_alert_id")
    @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="name")
    @JsonIdentityReference(alwaysAsId=true)
    protected MenuAlert menuAlert;
..
}
存储库中的此方法:

  @Transactional(propagation =Propagation.REQUIRED,
                    isolation=Isolation.SERIALIZABLE,
                    readOnly=false,
                    transactionManager="transactionManager")
    @Modifying
        @Query("update MenuAlertNotification n set n.read = :status where n.id in :notificationIdList and n.menuAlert.menu.user.id = :userId")
        void changemenuNotificationListReadStatus(  @Param("notificationIdList") List<Long> notificationIdList, 
                                                        @Param("userId") long userId, 
                                                        @Param("status") boolean status);

该错误是由于数据库要删除一条记录,而其他记录引用了外键。(外键约束)

我猜在您的测试用例中,在您解析的代码片段之前,有一个删除操作代码,类似于

MenuAlertRepository.deleteAll()

当存在事务时,Spring JPA不会立即执行此语句。在Spring JPA遇到JPQL查询(ChangeMenuTificationReadStatus)之后,它将所有缓存语句刷新到db中。此时,delete语句正在准确执行。然后抛出外键约束异常。

执行
MenuAlertNotification MenuAlertNotification=new MenuAlertNotification(menuAlert)时不会生成ID
以及
Long menuAlertNotificationId=menuAlertNotification.getId()这将始终返回
null

您应该将junit测试的第二行更改为

menuAlertNotification = menuAlertNotificationService.save(menuAlertNotification);
我假设您的服务
menuAlertNotificationService.save(menuAlertNotification)
返回类似于
返回通知repo.save(实体)
的内容


这样,在插入行后,新对象将填充ID,因此不会得到声明的异常。

正如Jian所说,导致错误的不是对ChangeMenuTificationReadStatus的调用,而是之前未刷新的语句

正在生成此delete语句,该语句负责FK约束冲突:

delete from t_menu_alert where id=?
在测试中,您可以使用
saveAndFlush
而不是
save
,并且可以定期使用
flush
方法发出SQL修改请求并查看问题所在

这里,JPA试图在删除引用之前删除
MenuAlert
,因此您可能知道FK约束会阻塞

由于通知对已删除的警报没有意义,您还可以级联删除:

@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.REMOVE)
或者在数据库级别更改删除操作时的FK约束
:CASCADE将删除引用
MenuAlertNotification
s,并设置NULL将通过在引用
MenuAlertNotification.menuAlert
时设置NULL来清除关联

您还可以编写java代码,根据条件删除
MenuAlert
之前的
MenuAlert通知

我很想看看你的全部测试代码

Adil Khalil,你是对的,如果直接使用Spring Data JPA Repository.save方法,我们需要获取返回值以获得更新的id。但在这里,我认为他调用了一个服务层,该层将返回更新的值:

@Service
public class MenuAlertNotificationService {
    private MenuAlertNotificationRepository repository;

    public MenuAlertNotification save(MenuAlertNotification entity) {
        return repository.save(entity);
    } 
}

问题是因为您使用的是内存中的数据库,当测试方法完成时,Junit会删除所有表,但顺序不正确

服务层代码应该依赖于存储库。但是,要测试服务层,您不需要知道或关心持久层是如何实现的

理想情况下,您应该能够编写和测试我们的服务层代码,而无需在整个持久层中进行连接


要实现这一点,您可以使用Spring Boot Test提供的模拟支持。

我认为问题在于“n.menuAlert.menu.user.id=:userId”,因为您是孩子的孩子的访问属性。将它与id进行比较,这就是为什么会出现这个问题。由于MenuAlert是渴望的,所以它被抓取,但它的子对象不能像menu和menu的子用户那样被抓取,因此它们的FetchType将是惰性的。由于它们在运行时无法获取,因此可能会出现此问题。我猜您正在单元测试中创建一个新的menuAlert,并且测试框架正在尝试在测试结束时删除它。你能在测试中包括整个单元测试和注释吗?是的,如果我们的答案不能解决问题,请添加整个测试。请查看我的答案,如果有帮助,请相应地标记它
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.REMOVE)
@Service
public class MenuAlertNotificationService {
    private MenuAlertNotificationRepository repository;

    public MenuAlertNotification save(MenuAlertNotification entity) {
        return repository.save(entity);
    } 
}