基于关联实体列表

时间:2018-04-12 07:47:18

标签: java spring hibernate repository

我正在使用Spring boot 1.5和Hibernate。我有2个实体,Person和PersonDetail并不总是存在。我需要根据Person列表检索PersonDetails列表,即使匹配的PersonDetails不存在也是如此。

所以我在PersonService中编写了buildFromPersonList,它运行良好。但是我已经在我的数据库中填充了1000个Person条目,不幸的是,构建PersonDetails列表大约需要3.5秒。

由于性能问题我试图在JPQL中进行操作,请查看findAllByPersons并帮助我改进它以从PersonList获取PersonDetails并在它存在时检索匹配的PersonDetails。

这是我的实体

@Entity
@Table(name = "person")
public class Person{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    protected Long id;
    //name,birthdate ...

}
@Entity
@Table(name = "person_details")
public class PersonDetails{
// private details accessible only for authorized user
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    protected Long id;
    @OneToOne(cascade = CascadeType.MERGE)
    @JoinColumn(name = "id_person",insertable = true,updatable=true,nullable = false)
    protected Person person;

}

存储库

@Transactional
public interface PersonDetailsRepository extends JpaRepository<PersonDetails,Long> {
    PersonDetails findByPerson(Person person);
    // @Query("SELECT CASE WHEN (pd is not null ) THEN pd ELSE (new PersonDetails(p)) END  FROM Person p left join PersonDetails pd on p.id=pd.person.id")
    @Query("SELECT new PersonDetails(p) FROM Person p")
    List<PersonDetails> findAllByPersons();

}

服务

@Service
public class PersonDetailsService {

    private final PersonDetailsRepository personDetailsRepository;
    private final PersonService personService;
    // constructors + findall, findOne,save

    @Override
    public List<PersonDetails> findAll() {
        List<Person> personList=personService.findAll();
        return buildFromList(personList);
     //   return personDetailsRepository.findAllByPerson();
    }

    private List<PersonDetails> buildFromPersonList( List<Person> personList) {

        List<PersonDetails> personDetailsList= new ArrayList<>();

        for (Person person:personList) {
            PersonDetails personDetails = personDetailsRepository.findByPersonperson);
            if(personDetails==null){
                personDetails=new PersonDetails();
                personDetails.setPerson(person);
            }
            personDetailsList.add(personDetail);

        }
        return personDetailsList;
    }
}

更新:我已经实现了一个基于TheBakker理念的新解决方案,但它仍然需要花费太多时间来加载(仅在1000个条目之间800毫秒和1秒之间)。 有没有人想要更快地检索? 这是我的新代码:

@Transactional
public interface PersonDetailsRepository extends JpaRepository<PersonDetails,Long> {
    //..
    @Query("SELECT new PersonDetails(p) FROM Person p WHERE p.id not in (SELECT pd.person.id From PersonDetails pd)")
List<PersonDetails> findAllPersonNotInPersonDetails();

}
 @Service
public class PersonDetailsService {

    @Override
    public List<PersonDetails> findAll() {
       List<PersonDetails> personDetailsList=personDetailsRepository.findAll();

   /*       personDetailsList.addAll(personDetailsRepository.findAllPersonsNotInPersonDetails());

    return personDetailsList;*/

return Stream.concat(personDetailsList.stream(), agentDetailsRepository.findAllPersonNotInPersonDetails().stream())
                .collect(Collectors.toList())
    }
}

1 个答案:

答案 0 :(得分:1)

实际上,您在数据库中执行了1000个选择查询,以获取每个人的personDetail。

更快(但仍可完成)的事情是进行2次查询:

  1. 获取数据库中所有PersonDetails的人
  2. 另一个会让你的列表中的所有人都没有PersonDetails并且你需要循环并实例化一个。
  3. 这样你就可以在2中改变1000个查询/交易,你应该肯定会获得一些。