Добрый день,
Используя Spring Boot + JPA + Hibernate, я ожидаю исключение при попытке удалить сущность, на которую все еще ссылается другая сущность (нарушение моего ограничения FK).Я использую CRUDRepository, и я ожидал, что смогу перехватить DataIntegrityViolationException из вызова delete или deleteById.
Однако ничего не происходит, и в журналах отображается только запрос выбора:
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
Зависимости:
- Spring Boot 2.1.2.RELEASE
- Postgresql 42.2.5
- Hibernate Core 5.3.7.Final