【发布时间】:2019-01-29 16:08:45
【问题描述】:
下午好,
使用 Spring Boot + JPA + Hibernate,我期待在尝试删除仍被另一个实体引用的实体时出现异常(违反我的 FK 约束)。我正在使用 CRUDRepository,我希望能够从 delete 或 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);
}
}
应用程序测试属性:
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
依赖关系:
- Spring Boot 2.1.2.RELEASE
- Postgresql 42.2.5
- Hibernate Core 5.3.7.Final
【问题讨论】:
-
删除 cascade.ALL 就可以了...
-
同意,但我仍然希望能够级联删除用户,所以这对我不起作用。而且它仍然没有告诉我为什么尝试直接删除外国实体不会触发完整性违规。
标签: java hibernate spring-boot jpa