I try to load initial json documents into mongodb database with spring boot. First, These are mongodb documents schema.
@Document(collection="Posts")
public class Post {
@Id
private String _id;
@Indexed(unique = true)
private Long id; // This field is used for compatibility with Jpa Service interface
private String title;
private String body;
private Date createdDate;
@DBRef
private User user;
@DBRef
private Collection<Tag> tags;
}
And below codes are the initial json file contents.
[ {
"Post" : {
"id" : 1,
"title" : "Title 1",
"created_date" : "2018-12-01 11:10:13.247",
"body" : " 국회는 헌법 또는 ....",
"user" : {
"username" : "joseph",
"password" : "password"
},
"tags" : {
"tag" : [
{
"id" : 1,
"created_Date" : "2018-12-02 11:10:13.247",
"body" : "첫 글의 댓글입니다.",
"user" : {
"username" : "jina",
"password" : "password"
}
},{
"id" : 2,
"created_Date" : "2018-12-03 11:10:13.247",
"body" : "첫 글의 두번째 댓글입니다.",
"user" : {
"username" : "julian",
"password" : "password"
} } ] } }
}
,
{
"post" : {
"id" : 2,
"title" : "Title 2",
"created_date" : "2018-12-03 11:10:13.247",
"body" : "제안된 헌법개정안은 대통령이 ....",
"user" : {
"username" : "joseph",
"password" : "password"
},
"tags" : {
"tag" : [
{
"id" : 1,
"created_Date" : "2018-12-02 11:10:13.247",
"body" : "댓글 입니다.",
"user" : {
"username" : "julian",
"password" : "password"
} } ] } }
}]
And the last parts are the function which load the above initial json file into mongodb.
@Override
public void loadInitDocuments(String file) {
// TODO Auto-generated method stub
try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), "EUC-KR"))) {
String line;
StringBuffer strBuffer = new StringBuffer();
while ((line = br.readLine()) != null) {
strBuffer.append(line+ "\n");
}
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
TypeReference<List<Post>> typeReference = new TypeReference<List<Post>>(){};
Collection<Post> posts = objectMapper.readValue(strBuffer.toString(), typeReference);
System.out.println(posts.stream().collect(Collectors.toList()));
if(postMongoRepository.count() == 0) {
for(Post post : posts) {
postMongoRepository.save(post); // this line throws exception
}
}
br.close();
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
But MongoRepository.save line throws exception.
Caused by: com.mongodb.MongoWriteException: E11000 duplicate key error collection: Blog.Posts index: id dup key: { : null }
at com.mongodb.client.internal.MongoCollectionImpl.executeSingleWriteRequest(MongoCollectionImpl.java:967)
at com.mongodb.client.internal.MongoCollectionImpl.executeInsertOne(MongoCollectionImpl.java:494)
at com.mongodb.client.internal.MongoCollectionImpl.insertOne(MongoCollectionImpl.java:478)
at com.mongodb.client.internal.MongoCollectionImpl.insertOne(MongoCollectionImpl.java:472)
at org.springframework.data.mongodb.core.MongoTemplate$6.doInCollection(MongoTemplate.java:1436)
at org.springframework.data.mongodb.core.MongoTemplate.execute(MongoTemplate.java:538)
I found the reason with googling. The reason is "If a document does not have a value for the indexed field in a unique index, the index will store a null value for this document. Because of the unique constraint, MongoDB will only permit one document that lacks the indexed field." But I have no idea which part of json file has wrong value.
This time I face the problem with the @Dbref annotation part. Below is the User document codes,
@Document //
public class User {
@Id //(2)
private String _id;
@Indexed(unique = true)
private Long id;
@Indexed(unique=true)
private String username;
private String password;
}
And below are the modified initial json file contents.
[
{
"id" : 0,
"title" : "Title 1",
"created_date" : "2018-12-01 11:10:13.247",
"body" : " 국회는 헌법 또는 법률에 ",
"user" : {
"id" : 0,
"username" : "joseph",
"password" : "password"
},
"tag" : [
{
"id" : 0,
"created_Date" : "2018-12-02 11:10:13.247",
"body" : "첫 글의 댓글입니다.",
"user" : {
"id" : 1,
"username" : "jina",
"password" : "password"
}
},{
"id" : 1,
"created_Date" : "2018-12-03 11:10:13.247",
"body" : "첫 글의 두번째 댓글입니다.",
"user" : {
"id" : 2,
"username" : "julian",
"password" : "password"
}
} ] }
,
{
"id" : 1,
"title" : "Title 2",
"created_date" : "2018-12-03 11:10:13.247",
"body" : "제안된 헌법개정안은 대통령이 20",
"user" : {
"id" : 0,
"username" : "joseph",
"password" : "password"
},
"tag" : [
{
"id" : 0,
"created_Date" : "2018-12-02 11:10:13.247",
"body" : "댓글 입니다.",
"user" : {
"id" : 2,
"username" : "julian",
"password" : "password"
} } ] }
]
But the user
document is not bound with json file. The exception is...
Cannot create a reference to an object with a NULL id.
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:975)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writePropertyInternal(MappingMongoConverter.java:597)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeAssociation(MappingMongoConverter.java:560)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeProperties(MappingMongoConverter.java:537)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeInternal(MappingMongoConverter.java:524)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.writeInternal(MappingMongoConverter.java:497)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.write(MappingMongoConverter.java:441)
User
document is not bound with Post
document, so it return null value. When this line is executed it return false
for(Post post : posts) {
if(post.getUser().getId() == null)
System.out.println("YES!! It is null");
postMongoRepository.save(post);
}
In your initial json file, you have an array of 2 documents, which have only one root field : "Post" for first one, "post" for second one. So saving first document will result in id=null (as Post.id is defined, but not id). And the same with the second will throw error... Try replacing by, and it must work...
[ {
"id" : 1,
"title" : "Title 1",
"created_date" : "2018-12-01 11:10:13.247",
"body" : " 국회는 헌법 또는 ....",
"user" : {
"username" : "joseph",
"password" : "password"
},
"tags" : {
"tag" : [
{
"id" : 1,
"created_Date" : "2018-12-02 11:10:13.247",
"body" : "첫 글의 댓글입니다.",
"user" : {
"username" : "jina",
"password" : "password"
}
},{
"id" : 2,
"created_Date" : "2018-12-03 11:10:13.247",
"body" : "첫 글의 두번째 댓글입니다.",
"user" : {
"username" : "julian",
"password" : "password"
} } ] }
}
,
{
"id" : 2,
"title" : "Title 2",
"created_date" : "2018-12-03 11:10:13.247",
"body" : "제안된 헌법개정안은 대통령이 ....",
"user" : {
"username" : "joseph",
"password" : "password"
},
"tags" : {
"tag" : [
{
"id" : 1,
"created_Date" : "2018-12-02 11:10:13.247",
"body" : "댓글 입니다.",
"user" : {
"username" : "julian",
"password" : "password"
} } ] }
}]