简体   繁体   English

Spring + Mongodb的ID为空

[英]Spring + Mongodb with a Null id Issue

I'm working on a academic project with Spring + MongoDB 我正在使用Spring + MongoDB进行学术项目

I have three Document 我有三个文件

User.java User.java

@Document
public class User implements UserDetails, Serializable {
private static final long SerialVersionUID = 147147L;

@Id
private String id;

private String username;
private String password;
private String firstname;
private String lastname;

private String email;
private String phone;

private boolean enable = true;
private Set<UserRole> userRoles = new HashSet<>();

...

}

Role.java Role.java

@Document
public class Role implements Serializable {
private static final long SerialVersionUID = 456456L;
@Id
private String id;
private String name;
...

}

UserRole.java UserRole.java

@Document(collection = "user_roles")
public class UserRole implements Serializable {
private static final long SerialVersionUID = 789789L;

@Id
private String id;

@DBRef
private User user;

@DBRef
private Role role;

private String name;

...

}

And a UserServiceImpl.java 还有一个UserServiceImpl.java

@Service
public class UserServiceImpl implements UserService {
private static final Logger LOG = LoggerFactory.getLogger(UserService.class);

@Autowired
UserRepository userRepository;

@Autowired
RoleRepository roleRepository;

@Autowired
UserRoleRepository userRoleRepository;

@Override
public User createUser(User user, Set<UserRole> userRoles) {
    User localUser = userRepository.findByUsername(user.getUsername());

    if(localUser != null) {
        LOG.info("User with username {} already exist. Nothing will be done. ", user.getUsername());
    } else {
        for (UserRole ur : userRoles) {
            roleRepository.save(ur.getRole());
            //here is the problem: the userrole instance created cannot generate Id
            userRoleRepository.save(ur);
        }

        user.getUserRoles().addAll(userRoles);


        localUser = userRepository.save(user);
    }

    return localUser;
}

} }

and the DemoApplication.java 和DemoApplication.java

@SpringBootApplication
public class DemoApplication implements CommandLineRunner {
@Autowired
UserService userService;

public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
}

@Override
public void run(String... args) throws Exception {


User user1 = new User();
user1.setFirstname("John");
user1.setLastname("Adams");
user1.setUsername("j");
    user1.setPassword(SecurityUtility.passwordEncoder().encode("p"));
    user1.setEmail("JAdams@gmail.com");
    Set<UserRole> userRoles = new HashSet<>();
    Role role1 = new Role();
    role1.setName("ROLE_USER");
    UserRole userRole1 = new UserRole();
    userRole1.setRole(role1);
    userRole1.setUser(user1);
    userRoles.add(userRole1);

    userService.createUser(user1, userRoles);


    }

and the ExceptionStackTrack 和ExceptionStackTrack

java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:821) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:802) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:341) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1277) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1265) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at com.example.demo.DemoApplication.main(DemoApplication.java:22) [classes/:na]
Caused by: org.springframework.data.mapping.MappingException: Cannot create a reference to an object with a NULL id.
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.createDBRef(MappingMongoConverter.java:936) ~[spring-data-mongodb-2.0.10.RELEASE.jar:2.0.10.RELEASE]
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writePropertyInternal(MappingMongoConverter.java:554) ~[spring-data-mongodb-2.0.10.RELEASE.jar:2.0.10.RELEASE]
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeAssociation(MappingMongoConverter.java:517) ~[spring-data-mongodb-2.0.10.RELEASE.jar:2.0.10.RELEASE]
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeProperties(MappingMongoConverter.java:494) ~[spring-data-mongodb-2.0.10.RELEASE.jar:2.0.10.RELEASE]
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeInternal(MappingMongoConverter.java:481) ~[spring-data-mongodb-2.0.10.RELEASE.jar:2.0.10.RELEASE]
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeInternal(MappingMongoConverter.java:455) ~[spring-data-mongodb-2.0.10.RELEASE.jar:2.0.10.RELEASE]
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.write(MappingMongoConverter.java:399) ~[spring-data-mongodb-2.0.10.RELEASE.jar:2.0.10.RELEASE]
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.write(MappingMongoConverter.java:78) ~[spring-data-mongodb-2.0.10.RELEASE.jar:2.0.10.RELEASE]
at org.springframework.data.mongodb.core.MongoTemplate.toDocument(MongoTemplate.java:1071) ~[spring-data-mongodb-2.0.10.RELEASE.jar:2.0.10.RELEASE]
at org.springframework.data.mongodb.core.MongoTemplate.doSave(MongoTemplate.java:1254) ~[spring-data-mongodb-2.0.10.RELEASE.jar:2.0.10.RELEASE]
at org.springframework.data.mongodb.core.MongoTemplate.save(MongoTemplate.java:1202) ~[spring-data-mongodb-2.0.10.RELEASE.jar:2.0.10.RELEASE]
at org.springframework.data.mongodb.repository.support.SimpleMongoRepository.save(SimpleMongoRepository.java:82) ~[spring-data-mongodb-2.0.10.RELEASE.jar:2.0.10.RELEASE]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:377) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:200) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:641) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:605) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:590) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:59) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61) ~[spring-data-commons-2.0.10.RELEASE.jar:2.0.10.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at com.sun.proxy.$Proxy73.save(Unknown Source) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:197) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) ~[spring-tx-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.0.9.RELEASE.jar:5.0.9.RELEASE]
at com.sun.proxy.$Proxy73.save(Unknown Source) ~[na:na]
at com.example.demo.Service.Impl.UserServiceImpl.createUser(UserServiceImpl.java:42) ~[classes/:na]
at com.example.demo.DemoApplication.run(DemoApplication.java:46) [classes/:na]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:818) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
... 5 common frames omitted

Here I dont't know why roles and users instance can generate automatically but userrole cannot. 在这里,我不知道为什么角色和用户实例可以自动生成,而userrole无法生成。 The console return me an exception that the Id is NULL and cannot be reference. 控制台向我返回了一个异常,即Id为NULL,无法引用。

I'm new for this, and I hope someone could give me an answer. 我对此并不陌生,希望有人能给我答案。

thanks. 谢谢。

It seems that you are calling userRoleRepository.save(ur) in case when the User with the provided username does not exist in the database and before actually storing this User in it. 似乎您正在调用userRoleRepository.save(ur) ,以防数据库中不存在具有提供的用户名的User并且实际上没有将该User存储在数据库中。

I believe you should reorganise your code in a way to store the User first and then store the UserRole with this User set. 我相信您应该以一种方式来重新组织代码,以先存储User ,然后再使用该User集存储UserRole

In other words (code?), in your UserServiceImpl you could try doing something like this: 换句话说(代码?),您可以在UserServiceImpl尝试执行以下操作:

@Override
public User createUser(User user, Set<UserRole> userRoles) {
    User localUser = userRepository.findByUsername(user.getUsername());

    if(localUser != null) {
        LOG.info("User with username {} already exist. Nothing will be done. ", user.getUsername());
    } else {
        user.getUserRoles().addAll(userRoles);
        localUser = userRepository.save(user);
        for (UserRole ur : userRoles) {
            roleRepository.save(ur.getRole());
            userRoleRepository.save(ur);
        }
    }

    return localUser;
}

As you can see, I have only reordered the calls - User is stored first, then go the userRoles for this User . 如您所见,我仅对呼叫进行了重新排序-首先存储了User ,然后转到了该UseruserRoles

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM