我正在使用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个查询/事务,那么您肯定会获得一些。