我正在使用Spring Boot 1.5和Hibernate。我有2个实体,Person和PersonDetail并不总是存在。即使不存在匹配的PersonDetails,我也需要基于Person列表检索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的想法实现了一个新的解决方案,但是仍然需要花费很多时间来加载(800ms到1s之间只能加载1000个条目)。
有没有人想更快地找回东西?
这是我的新代码:

@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())
    }
}

最佳答案

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

会更快(但仍然很完美)的事情是执行两个查询:


一种已经在数据库中获取所有PersonDetails的代码
另一个将从列表中获取所有没有PersonDetails的人,您将需要为其循环并实例化一个人。


这样一来,您在2中更改了1000个查询/事务,那么您肯定会获得一些。

09-27 07:04