有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何使用saveAll()方法插入或更新(而不仅仅是插入)

我有一个名为User

我正在执行一项任务,希望从CSV/XLSX文件中插入多个用户

我可以保存所有的记录

List<User> userList = new ArrayList<>();


for (int i = 0; i < worksheet.getPhysicalNumberOfRows(); i++) {
                User user = new User();
                XSSFRow row = worksheet.getRow(i);
                user.setName(row.getCell(0).getStringCellValue());
                userList.add(user);
            }
userRepository.saveAll(userList);

但现在的问题是,如果文件包含重复的记录,或者如果我试图再次插入同一个用户,那么它也会保存在表中,我不希望这样

我想让用户没有重复的名字

我的实体很简单,有如下字段

private Long userId;
private String name;

让我知道如何避免重复记录插入

任何帮助都将不胜感激

注意事项:

我知道如何从arraylist中删除重复项。这不是问题所在。问题是,如果我试图从新的CSV/XLSX文件中添加记录,并且该文件的名称与表中可用的名称相同,那么我不想在表中插入这些名称


共 (3) 个答案

  1. # 1 楼答案

    我建议您不要使用List<User>,而是根据需要使用Set<User>并重写hashCode()和equals()

    阅读了note部分后,如果只想在表中插入新名称而不更改实体结构,可以执行以下操作:

    interface UserRepository extends JPARepository {
      public List<User> findByName(List<String> names);
    }
    

    您可以使用上述方法从未保存的用户列表中获取已经存在的名称记录,删除重复项并保存剩余的名称

  2. # 2 楼答案

    List<User> userList = new ArrayList<>();
    
    
    for (int i = 0; i < worksheet.getPhysicalNumberOfRows(); i++) {
                User user = new User();
                XSSFRow row = worksheet.getRow(i);
    
                User testUser = userList.get(userList.size()-1) //returns the last user
                testUser.setName(row.getCell(0).getStringCellValue());
    
                if (userList.contains(testUser)) continue; //skips
    
                user.setName(row.getCell(0).getStringCellValue());
                userList.add(user);
            }
    userRepository.saveAll(userList);
    

    现在,简单地说,您将获取保存的最后一个用户,并将其添加到变量testUser中,以获取最后一个id,然后设置名称并检查该用户是否已经存在

  3. # 3 楼答案

    解决方案1

    Spring Jpa默认情况下会更新一个实体(如果它已经存在)。否则它将创建一个新的

    我假设您在excel文件中没有提供任何Id,因此对于JPA,当您调用saveAll时,所有实体都被视为新实体,只执行Insert语句

    如果您已经提供了现有id,那么对于现有id,将执行update语句

    因此,解决问题的一个简单方法是为现有实体提供Id

    将此方法添加到您的存储库中,并对其进行调整,以使其能够工作,因为您没有实体的所有相关信息(可能有些方法拼写错误)

    @Query(value ="SELECT u.name, u.userId " +
            "FROM User u " +
            "WHERE u.name IN :namesList" )
     List<Object[]> retrieveIdsWithNames(@Param("namesList") List<String> namesList);
    

    然后,您可以使用所有现有ID增强saveAll列表

        for (int i = 0; i < worksheet.getPhysicalNumberOfRows(); i++) {
                        User user = new User();
                        XSSFRow row = worksheet.getRow(i);
                        user.setName(row.getCell(0).getStringCellValue());
                        userList.add(user);
                    }
    
        Map<String, Long> nameIdMap = repo.retrieveIdsWithNames(userList.stream().map(v -> v.getName()).collect(Collectors.toList())).stream()
                .collect(Collectors.toMap((arr->arr[0].toString()), (arr->Long.valueOf(arr[1].toString()))));;
    
    //Enhance the list you are going to persist with the existing ids
    userList.forEach(u -> {
    if (nameIdMap.containsKey(u.getName()) {
         u.setUserId(nameIdMap.get(u.getName());
       }
      }
        userRepository.saveAll(userList);
    

    解决方案2

    如果您负担得起,请将实体的id更改为您能够提供的名称。在该实体上更新hashcode和equals,那么在您的案例场景中,默认情况下一切都会正常工作