我的实体被映射到数据库表。
我需要将其重新映射到具有where条件的另一个表。最简单的方法是创建一个数据库视图。
create view person_main_asg as (
select * from person_history
where asg_end_date is null or asg_end_date > CURRENT_TIMESTAMP
)
问题是我没有权限创建它。
所以我需要在spring-boot应用程序中解决问题。
Google搜索我发现我可以在实体定义中添加过滤器。
@Entity
@FilterDef(name="person_history_main_asg")
@Filter(name="person_history_main_asg", condition = "asg_end_date is null or asg_end_date > CURRENT_TIMESTAMP) ")
@Table(name = "person_history")
public class Person {
///...
}
现在我需要启用我的过滤器,因为它默认是禁用的。
结果证明这是一项艰巨的任务。
一个solution是使用AOP / AspectJ。在我看来,它更像是一个hack而不是一个答案,但主要的问题是它需要通过添加javaagent:path/to/aspectjweaver.jar
来修改VM参数,我不允许这样做。
另一种解决方案是实现一个当前定义为接口的存储库
public interface PersonRepository {
Person findByFullLoginEndingWith(String login);
List<Person> findByFirstNameContainingIgnoreCase(String firstName);
List<Person> findByLastNameContainingIgnoreCase(String lastName);
}
所以实现应该是
public interface PersonRepositoryCustom {
Person findByFullLoginEndingWith(String login);
List<Person> findByFirstNameContainingIgnoreCase(String firstName);
List<Person> findByLastNameContainingIgnoreCase(String lastName);
}
public interface PersonRepository extends Repository<Person, String>, JpaSpecificationExecutor<Person>, PersonRepositoryCustom {
}
public class PersonRepositoryImpl implements PersonRepositoryCustom {
@PersistenceContext
private EntityManager entityManager;
@Autowired
private PersonRepository personRepository;
public Person findOne(Specification<Person> spec) {
Filter filter = (Filter)entityManager.unwrap(Session.class).enableFilter("person_history_main_asg");
Person result = personRepository.findOne(spec);
return result;
}
public Person findOne(String id) {
//...
}
public List<Person> findAll() {
//...
}
public List<Person> findAll(Specification<Person> spec) {
//...
}
//...
}
我对这个解决方案有几个问题(此外它是大量的和重的)。
EntityManager导致以下错误:没有定义[javax.persistence.EntityManagerFactory]类型的限定bean:期望的单个匹配bean但找到了4
另外
@Autowired
private PersonRepository personRepository;
导致stackoverflow,因为它是PersonRepositoryImpl
的一个实例,它是自动装配的,但我需要通过Springboot访问默认实现。
那么我如何在我的应用程序中模拟数据库视图?
编辑:
目前我的实体已映射到另一个表。 我的实体存储库定义为
public interface PersonRepository extends Repository<Person, String>, JpaSpecificationExecutor<Person> {
T findOne(ID id);
List<T> findAll();
Person findByFullLoginEndingWith(String login);
List<Person> findByFirstNameContainingIgnoreCase(String firstName);
List<Person> findByLastNameContainingIgnoreCase(String lastName);
}
答案 0 :(得分:1)
您不需要实施,不需要过滤器,您不需要视图。只需定义查询方法并使用@Query
注释即可。
public interface PersonRepository extends JpaRepository {
Person findByFullLoginEndingWith(String login);
List<Person> findByFirstNameContainingIgnoreCase(String firstName);
List<Person> findByLastNameContainingIgnoreCase(String lastName);
@Query(value="select * from person_history where asg_end_date is null or asg_end_date > CURRENT_TIMESTAMP", nativeQuery=true)
List<Person> findPersonMain();
}
这就是你所需要的,没有自定义实现等,因为Spring Data JPA将知道如何处理它。目前它是一个本机查询,但您可以将其重写为JPQL。
=============================================== ======================
Oleg Pavliv编辑:
解决方案是使用@Where而不是@Filter(取自评论的主题)。
@Entity
@Where(clause = "asg_end_date is null or asg_end_date > GETDATE()) ")
@Table(name = "person_history")
public class Person {
///...
}