CRUDRepository::d elete 静默执行,而执行应违反 FK 并引发异常



下午好,

使用 Spring Boot + JPA + Hibernate,我在尝试删除仍被另一个实体引用的实体时预计会出现异常(违反我的 FK 约束)。我正在使用CRUDRepository,我希望能够从删除或deleteById调用中捕获DataIntegrityViolationException。

但是,没有任何反应,日志仅显示选择查询:

Hibernate: select jpauserpas0_.id as id1_4_0_, jpauserpas0_.cdate as cdate2_4_0_, jpauserpas0_.password as password3_4_0_, jpauser1_.id as id1_3_1_, jpauser1_.cdate as cdate2_3_1_, jpauser1_.pid as pid4_3_1_, jpauser1_.username as username3_3_1_ from user_password jpauserpas0_ left outer join "user" jpauser1_ on jpauserpas0_.id=jpauser1_.pid where jpauserpas0_.id=?

有人知道为什么会这样吗?这是正常行为吗?

型:

public class JPAUser
{
    @Id
    @GeneratedValue(generator = "genuser", strategy = GenerationType.SEQUENCE)
    @SequenceGenerator(name = "genuser", sequenceName = "user_id_seq", allocationSize=1)
    public Integer id;
    @Column(unique = true)
    public String username;
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "pid")
    public JPAUserPassword password;
    public JPAUser(String username, JPAUserPassword password)
    {
        this.username = username;
        this.password = password;
    }
    ...
}
public class JPAUserPassword
{
    @Id
    @GeneratedValue(generator = "genupwd", strategy = GenerationType.SEQUENCE)
    @SequenceGenerator(name = "genupwd", sequenceName = "upwd_id_seq", allocationSize=1)
    public Integer id;
    @Column(nullable=false, updatable=false)
    public String value;
    @OneToOne(mappedBy = "password")
    public JPAUser user;
    public JPAUserPassword(String value)
    {
        this.password = value;
    }
    ...
}

法典:

@Configuration
@EnableAutoConfiguration
@ComponentScan
@EntityScan("model.package.name")
@EnableJpaRepositories("repository.package.name")
public class JPATestConfiguration
{
    @Autowired
    Environment env;
    @Bean
    public DataSource dataSource()
    {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(env.getProperty("spring.datasource.driver-class-name"));
        dataSource.setUrl(env.getProperty("spring.datasource.url"));
        dataSource.setUsername(env.getProperty("spring.datasource.username"));
        dataSource.setPassword(env.getProperty("spring.datasource.password"));
        return dataSource;
    }
}
@Repository
public interface JPAUserRepository extends CrudRepository<JPAUser, Integer>
{
}
@Repository
public interface JPAUserPasswordRepository extends CrudRepository<JPAUserPassword, Integer>
{
}
@RunWith(SpringJUnit4ClassRunner.class)
@TestPropertySource("classpath:/application-test.properties")
@SpringBootTest(classes={JPATestConfiguration.class})
public class JPAUserPasswordTest
{
    @Autowired
    private JPAUserPasswordRepository userPasswordRepository;
    @Autowired
    private JPAUserRepository userRepository;
    private final String USERNAME = "username";
    private final String PASSWORD = "password";
    @Test
    public void deleteAttachedEntity()
    {
        JPAUserPassword jpaUserPassword = new JPAUserPassword(PASSWORD);
        JPAUser jpaUser = new JPAUser(USERNAME, jpaUserPassword);
        userRepository.save(jpaUser);
        int id = jpaUserPassword.getId();
        // any of the two should throw the exception
        userPasswordRepository.delete(jpaUserPassword);
        userPasswordRepository.deleteById(id);
    }
}

application-test.properties:

spring.datasource.url=jdbc:postgresql://localhost/MYDB?useSSL=false
spring.datasource.username=username
spring.datasource.password=password
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

依赖:

  • 春季引导 2.1.2.发布
  • Postgresql 42.2.5
  • 休眠核心 5.3.7.最终版
// any of the two should throw the exception
userPasswordRepository.delete(jpaUserPassword);
userPasswordRepository.deleteById(id);
Above will delete record from child entity JPA`enter code here`UserPassword, so constraint violation error won't come.
If constraint violation is required on JPAUser, then remove CascadeType.ALL or make it CascadeType.PERSIST

最新更新