在spring-boot应用程序

时间:2017-06-14 06:01:04

标签: hibernate spring-boot

我的实体被映射到数据库表。

我需要将其重新映射到具有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);
}

1 个答案:

答案 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 {
///...
}