我正在使用 Spring boot 1.5 和 Hibernate。我有 2 个实体,Person 和 PersonDetail,它们并不总是存在。我需要根据人员列表检索人员详细信息列表,即使匹配的人员详细信息不存在也是如此。
所以我在PersonService中编写了buildFromPersonList,它运行良好。但是,我已经用 1000 个 Person 条目填充了我的数据库,不幸的是,构建 PersonDetails 列表大约需要 3,5 秒。
由于性能问题,我正在尝试在 JPQL 中执行此操作,请查看 findAllByPeople 并帮助我改进它以从 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 想法的新解决方案,但加载仍然需要太多时间(仅 800 个条目在 1 毫秒到 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())
}
}
实际上,您在数据库中执行 1000 个选择查询,以获取每个单独的 Person 的 personDetail。
更快(但仍然可以完善(的事情是执行 2 个查询:
- 一个获取数据库中已有的所有人员详细信息
- 另一个将从您的列表中获取所有没有 PersonDetails 的人,您需要为其循环并实例化一个。
这样,您在 2 中更改了 1000 个查询/事务,并且您肯定会获得一些查询/事务。