使用 spring 数据 jpa 存储库在 Hql 查询之后进行 flush()
flush() after Hql querie using spring data jpa repository
我正在 spring 数据 jpa 存储库中使用 @Query
注释编写一些 hql 查询。我知道我可以使用存储库接口中的方法,但出于学习目的,我正在明确编写它们。
这是我的主要内容class
@SpringBootApplication
public class Main implements CommandLineRunner {
@Autowired
PersonRepository personRepository;
public static void main( String[] args ) {
SpringApplication.run(Main.class, args);
}
/**
* if we delete the transactional annotation-> we get an exception
*/
@Override
@Transactional
public void run( String... args ) throws Exception {
saveOperation();
deleteOperationUsingHql();
}
private void saveOperation() {
Person p = new Person("jean", LocalDate.of(1977,12,12));
personRepository.save(p);
}
private void deleteOperationUsingHql() {
personRepository.deleteUsingHql(1L);
personRepository.flush();
Optional<Person> p = personRepository.findById(1L);
if (p.isPresent()){
System.out.println("still present");
}
}
}
我的 personRepository 接口
public interface PersonRepository extends JpaRepository<Person, Long> {
@Query(value = "select p from Person p where p.id=?1")
List<Person> getById( Long id);
@Modifying
@Query(value = "delete from Person p where p.id=:id")
void deleteUsingHql( Long id );
}
这个人class
@Entity
@Table(name = "Person")
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private LocalDate date;
// constructors,getters...omitted for brievety
}
一切都运行很好,但是对于deleteOperationUsingHql()
,即使我从数据库中删除了这个人,即使我将修改刷新到数据库,这个人id=1
] 仍然由 findById(1L)
方法返回。我应该怎么做才能使 findById(1L)
返回一个空的 Optional.
我的第二个问题是关于@Transactional
注释,我知道它的详细工作原理,但我不知道为什么如果我们删除它,我们会得到以下异常
Caused by: javax.persistence.TransactionRequiredException: Executing
an update/delete query
有人可以解释为什么我在 @Transactional
被删除时会收到此异常。
even If I deleted the person from the database and even if I flush the modification to the database, the person with id=1 is still returned by the findById(1L) method
这很正常,因为您使用查询来删除人员,而不是实际使用存储库(以及 EntityManager)删除方法。查询完全绕过会话缓存,因此 Hibernate 不知道这个人已被删除,returns 实例在其缓存中。解决方案:不要使用查询。替代解决方案,删除后清除缓存(例如通过将 Modifying
注释的 clearAutomatically
标志设置为 true)。
Could someone explains why I'm getting this exception when @Transactional is removed.
因为删除@Transactional
时,在执行该方法之前没有SPring启动事务,从报错信息可以看出,删除查询必须在事务内部执行.
我正在 spring 数据 jpa 存储库中使用 @Query
注释编写一些 hql 查询。我知道我可以使用存储库接口中的方法,但出于学习目的,我正在明确编写它们。
这是我的主要内容class
@SpringBootApplication
public class Main implements CommandLineRunner {
@Autowired
PersonRepository personRepository;
public static void main( String[] args ) {
SpringApplication.run(Main.class, args);
}
/**
* if we delete the transactional annotation-> we get an exception
*/
@Override
@Transactional
public void run( String... args ) throws Exception {
saveOperation();
deleteOperationUsingHql();
}
private void saveOperation() {
Person p = new Person("jean", LocalDate.of(1977,12,12));
personRepository.save(p);
}
private void deleteOperationUsingHql() {
personRepository.deleteUsingHql(1L);
personRepository.flush();
Optional<Person> p = personRepository.findById(1L);
if (p.isPresent()){
System.out.println("still present");
}
}
}
我的 personRepository 接口
public interface PersonRepository extends JpaRepository<Person, Long> {
@Query(value = "select p from Person p where p.id=?1")
List<Person> getById( Long id);
@Modifying
@Query(value = "delete from Person p where p.id=:id")
void deleteUsingHql( Long id );
}
这个人class
@Entity
@Table(name = "Person")
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private LocalDate date;
// constructors,getters...omitted for brievety
}
一切都运行很好,但是对于deleteOperationUsingHql()
,即使我从数据库中删除了这个人,即使我将修改刷新到数据库,这个人id=1
] 仍然由 findById(1L)
方法返回。我应该怎么做才能使 findById(1L)
返回一个空的 Optional.
我的第二个问题是关于@Transactional
注释,我知道它的详细工作原理,但我不知道为什么如果我们删除它,我们会得到以下异常
Caused by: javax.persistence.TransactionRequiredException: Executing an update/delete query
有人可以解释为什么我在 @Transactional
被删除时会收到此异常。
even If I deleted the person from the database and even if I flush the modification to the database, the person with id=1 is still returned by the findById(1L) method
这很正常,因为您使用查询来删除人员,而不是实际使用存储库(以及 EntityManager)删除方法。查询完全绕过会话缓存,因此 Hibernate 不知道这个人已被删除,returns 实例在其缓存中。解决方案:不要使用查询。替代解决方案,删除后清除缓存(例如通过将 Modifying
注释的 clearAutomatically
标志设置为 true)。
Could someone explains why I'm getting this exception when @Transactional is removed.
因为删除@Transactional
时,在执行该方法之前没有SPring启动事务,从报错信息可以看出,删除查询必须在事务内部执行.