couchbase pagingandsortingrepository.save()异常行为?

khbbv19g  于 2021-06-27  发布在  Java
关注(0)|答案(0)|浏览(269)

大家好,提前感谢大家看了这个问题。我正在JavaSpringBoot(JavaJDK1.8版)上使用couchbase服务器社区6.6.0。
问题描述:为了与couchbase交互,我使用了pagingandsortingrepository。每次我调用.save()时,都会在couchbase中创建一个新文档,表示我正在使用的对象的新示例。另外,当我从couchbase检索一个对象时,更改某个字段的值,例如,.setpassword(),然后调用.save()使更改持久化,然后在couchbase中创建该对象的新文档(具有新id)。在我看来,当我调用.save()时,数据库中似乎存在该对象的许多不同版本,我想确保我一直在处理对象/实体示例的最新版本。
我真的很困惑!我要做的应该是简单明了的,每次我更新一个java实体时,我都希望对couchbase中的文档(使用该文档id)进行持久化的更改。也许我错过了什么。请给我建议。
pom的局部视图如下所示:

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
...

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-couchbase</artifactId>
        </dependency>

实体如下:

@Data
@Document
@CompositeQueryIndex(fields = {"id", "userName"})
public class User implements Serializable {

    private static final long serialVersionUID = 1L;

    @IdPrefix
    private String prefix;

    @Id @NotNull @GeneratedValue( delimiter = "::", strategy = GenerationStrategy.UNIQUE)
    private String id;

    @Field
    @NotNull
    @Size(min=2, max=40)
    private String firstname;

    @Field
    @NotNull
    @QueryIndexed
    private String username;

    //Other attributes here ...
}

//ConfirmationToken Entity

@Data
@NoArgsConstructor
@CompositeQueryIndex(fields = {"id", "confirmationToken"})
public class ConfirmationToken {

    @IdPrefix
    private String prefix = "token";

    @Id @NotNull @GeneratedValue(delimiter = "::", strategy = GenerationStrategy.UNIQUE)
    private String id;

    @Field
    @Reference
    private User user;

    @Field
    @QueryIndexed
    private String confirmationToken;

     //Other attributes here ...

}

userrepository看起来像:

@Repository
public interface UserRepository extends PagingAndSortingRepository<User, Long> {

    @ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS)
    List<User> findByUsername(String username);

}

@Service
@AllArgsConstructor
public class ConfirmationTokenServiceImpl implements ConfirmationTokenService {

    @Autowired
    private final ConfirmationTokenRepository confirmationTokenRepository;  

    @Override
    public void saveConfirmationToken(ConfirmationToken confirmToken) {
        confirmationTokenRepository.save(confirmToken);
    }

}//end class

当我想从couchbase检索用户对象时,我会执行以下操作:

//How do I ensure this Object is the latest version of that document?
  List<User> users = userRepository.findByUsername(username);

  //The following does not ensure that I get the latest version of that User document with that username
  User testUser = users.get(users.size()-1);

在某些方法中,我更改java对象(即user)的字段值,然后在调用.save(user对象)时在数据库中创建该用户文档的新修订版。如何更新该用户对象的字段并使该文档在数据库中持久化,而不创建该文档的新修订版?另外,我如何确保我总是获得并处理该用户文档的最新版本?

public void someMethod(UserDTO regForm, final String contextPath) {

        User testUser = new User();

        testUser.setFirstname(regForm.getFname());
        testUser.setLastname(regForm.getSname());

        //Make User persistent
        userRepository.save(testUser);

        //Create the confirmation token for that User instance
        final ConfirmationToken confirmToken = new ConfirmationToken(testUser);

        confirmationTokenService.saveConfirmationToken(confirmToken);
}

在这个方法中,我有另一个名为confirmationtoken的类,它引用了一个用户对象。这是将每个confirmationtoken示例与特定的用户示例相关联。当我调用以下方法来更改用户密码时,将为数据库中的用户创建一个具有新id的新文档。我无法理解如何更新当前示例。请帮忙。

public void changeUserPassword(ConfirmationToken confirmToken, ResetPassDTO resetPassForm) {

        //Retrieve the User instance that is associated with that Token 
        final User testUser = confirmToken.getUser();

        if (testUser.getEmail().equals(resetPassForm.getEmail())) {

            //Get the Hash of the User's password
            final String encryptedPassword = bCryptPasswordEncoder.encode(resetPassForm.getNewPassword());
            testUser.setPassword(encryptedPassword);

            //Enable the user account - since email ownership is also verified
            testUser.setIsEnabled(true);

            userRepository.save(testUser);

        }

        //Delete the Confirmation Token entity      
        confirmationTokenService.deleteConfirmationToken(confirmToken); 

    }

更新:
似乎我不得不回去为实体建立领域模型。更具体地说,考虑couchbase如何进行文档嵌入以及何时进行引用。在我的示例中,confirmationtoken示例持有对用户示例的引用。实际上,confirmationtoken将用户示例嵌入到同一个json文档中。但我无法访问所需的实际用户对象。换句话说,我似乎无法从confirmationtoken示例中通过跟随user对象的id来取消引用并获取用户示例。我的解决方法:我引入了一个 uuid 字段,然后从confirmationtoken获取用户示例的引用,然后调用 userRepository.findByUuid(userFromToken.getUuid()); 只有那时我才能得到我想要的实际用户对象。我的问题是为什么couchbase-spring-sdk不能自动取消引用?而且,似乎当我更改某个属性的值时,更改不会发生在实际对象上,而是发生在嵌入对象上,因此每次我都需要手动执行此取消引用以获取实际对象。这类似于mongodb@dbrefs??不确定是否有使用n1ql和嵌套查询的解决方案?我能用n1ql实现这一点吗?

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题