kaiso / relmongo Goto Github PK
View Code? Open in Web Editor NEWJava relationship-enabled domain model persistence framework for MongoDB
Home Page: https://kaiso.github.io/relmongo
License: Apache License 2.0
Java relationship-enabled domain model persistence framework for MongoDB
Home Page: https://kaiso.github.io/relmongo
License: Apache License 2.0
this will allow identifying referenced object collection when browsing the database
It would be nice to have a ManyToMany
annotation that works similar to the JPA annotation.
I'm trying to create relation with Long
id. Application throws next exception:
java.lang.ClassCastException: class java.lang.Long cannot be cast to class org.bson.types.ObjectId (java.lang.Long is in module java.base of loader 'bootstrap'; org.bson.types.ObjectId is in unnamed module of loader 'app')
at org.bson.Document.getObjectId(Document.java:249)
at io.github.kaiso.relmongo.mongo.DocumentUtils.mapIdentifier(DocumentUtils.java:63)
at io.github.kaiso.relmongo.mongo.PersistentRelationResolver.resolveOnLoading(PersistentRelationResolver.java:56)
at io.github.kaiso.relmongo.events.processor.RelMongoProcessor.onAfterLoad(RelMongoProcessor.java:57)
at org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener.onApplicationEvent(AbstractMongoEventListener.java:56)
at org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener.onApplicationEvent(AbstractMongoEventListener.java:31)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:400)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:354)
at org.springframework.data.mongodb.core.ReactiveMongoTemplate.maybeEmitEvent(ReactiveMongoTemplate.java:2009)
at org.springframework.data.mongodb.core.ReactiveMongoTemplate$ProjectingReadCallback.doWith(ReactiveMongoTemplate.java:2588)
at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:100)
at com.mongodb.reactivestreams.client.internal.ObservableToPublisher$1.onNext(ObservableToPublisher.java:68)
at com.mongodb.async.client.AbstractSubscription.onNext(AbstractSubscription.java:135)
at com.mongodb.async.client.AbstractSubscription.processResultsQueue(AbstractSubscription.java:203)
at com.mongodb.async.client.AbstractSubscription.tryProcessResultsQueue(AbstractSubscription.java:159)
at com.mongodb.async.client.AbstractSubscription.addToQueue(AbstractSubscription.java:117)
at com.mongodb.async.client.MongoIterableSubscription$2.onResult(MongoIterableSubscription.java:101)
at com.mongodb.async.client.MongoIterableSubscription$2.onResult(MongoIterableSubscription.java:87)
at com.mongodb.operation.AsyncQueryBatchCursor.next(AsyncQueryBatchCursor.java:135)
at com.mongodb.operation.AsyncQueryBatchCursor.next(AsyncQueryBatchCursor.java:99)
at com.mongodb.async.client.MongoIterableSubscription.requestMoreData(MongoIterableSubscription.java:87)
at com.mongodb.async.client.MongoIterableSubscription$1.onResult(MongoIterableSubscription.java:55)
at com.mongodb.async.client.MongoIterableSubscription$1.onResult(MongoIterableSubscription.java:48)
at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:49)
at com.mongodb.async.client.AsyncOperationExecutorImpl$1$1.onResult(AsyncOperationExecutorImpl.java:70)
at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:49)
at com.mongodb.operation.FindOperation$3.onResult(FindOperation.java:822)
at com.mongodb.operation.OperationHelper$ReferenceCountedReleasingWrappedCallback.onResult(OperationHelper.java:353)
at com.mongodb.operation.CommandOperationHelper$1.onResult(CommandOperationHelper.java:389)
at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:49)
at com.mongodb.connection.DefaultServer$DefaultServerProtocolExecutor$2.onResult(DefaultServer.java:207)
at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:49)
at com.mongodb.connection.CommandProtocolImpl$1.onResult(CommandProtocolImpl.java:102)
at com.mongodb.connection.DefaultConnectionPool$PooledConnection$1.onResult(DefaultConnectionPool.java:458)
at com.mongodb.connection.UsageTrackingInternalConnection$2.onResult(UsageTrackingInternalConnection.java:110)
at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:49)
at com.mongodb.connection.InternalStreamConnection$2$1.onResult(InternalStreamConnection.java:381)
at com.mongodb.connection.InternalStreamConnection$2$1.onResult(InternalStreamConnection.java:359)
at com.mongodb.connection.InternalStreamConnection$MessageHeaderCallback$MessageCallback.onResult(InternalStreamConnection.java:651)
at com.mongodb.connection.InternalStreamConnection$MessageHeaderCallback$MessageCallback.onResult(InternalStreamConnection.java:618)
at com.mongodb.connection.InternalStreamConnection$5.completed(InternalStreamConnection.java:487)
at com.mongodb.connection.InternalStreamConnection$5.completed(InternalStreamConnection.java:484)
at com.mongodb.connection.netty.NettyStream.readAsync(NettyStream.java:236)
at com.mongodb.connection.netty.NettyStream.handleReadResponse(NettyStream.java:266)
at com.mongodb.connection.netty.NettyStream.access$600(NettyStream.java:66)
at com.mongodb.connection.netty.NettyStream$InboundBufferHandler.channelRead0(NettyStream.java:325)
at com.mongodb.connection.netty.NettyStream$InboundBufferHandler.channelRead0(NettyStream.java:322)
at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1434)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:965)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:628)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysPlain(NioEventLoop.java:528)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:482)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:442)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:834)
use the same code as @OneToMany when possible
I have a child Document that has an @id field of type String (as opposed to ObjectId). As per the documentation, if the related child document has no id ( does not exist in the database) it needs to be created and automatically linked to the parent document by RelMongo.
When I try to save the child document, I get a java.lang.IllegalArgumentException "Can not set java.lang.String field xxx.Person.id to org.bson.types.ObjectId"
In the checkIdentifier method of class io.github.kaiso.relmongo.events.callback.PersistentPropertyConvertingCallback a check is made to see if the Mongo id is null, and if so, a new ObjectId is generated.
if (id == null) {
objectIdReaderCallback.getIdField().set(obj, ObjectId.get());
}
However, the code above assumes the type of the id field is ObjectId and hence the exception.
when a query is a lookup aggregation do not load OneToOne association twice because it's already loaded by the lookup pipeline.
By executing a query to retrieve the parent documents that has a many to one relationship to child documents, relmongo will issue 100 queries to retrieve the child documents when the number of returned parent documents are 100. As the number of documents in mongodb increases, the queries being executed separately can easily affect the performance of the application. Is it possible to load all child documents by 1 queries instead of N queries?
I'm trying to reference an item inside a subcollection and it's not working. Collection and Subcollection are embedded.
Does this work?
Document
+Collection
+Subcollection
+Reference
While debugging #62 I found some issue when not using @Document(collection="cars")
In PersistentPropertySavingCallback
Line 115
String collection = ReflectionsUtil.getGenericType(field).getAnnotation(Document.class).collection();
Only a getter for collection()
is used. However like in my example you can define the collection name also by omitting document=
and just using the value attribute.
@Document("cars")
data class Car(
@Id
val id: String,
val name: String,
)
The logic therefore ignores the collection name. Unfortunately it does not solve the problem I mentioned above
I having an issue when I fetching objects that have relationship in more than one level. I have 3 different classes that reference to each other by a one-to-one relationship, as shown below.
@Document(collection = "products")
@TypeAlias(value = "product")
public class Product {
@Id
private String id;
private String name;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinProperty(name = "variations")
private List<ProductVariation> variations;
}
@Document(collection = "variations")
@TypeAlias(value = "variation")
public class ProductVariation {
@Id
private String variationId;
private String name;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinProperty(name = "options")
private List<Option> options;
}
@Document(collection = "options")
@TypeAlias(value = "option")
public class Option {
@Id
private String optionId;
private String text;
}
Through a spring-controller and spring repository I can add some data to MongoDB database. But then my issue starts. As you can see in the repsonse below the option does not have any text value when I use a ProductRepository
to fetch the data. I have checked the MongoDB database and the data has been saved correctly.
[
{
"id": "5ef4998e0a994e434d6cce86",
"name": "My Product Name",
"variations": [
{
"id": "5ef4998e0a994e434d6cce84",
"name": "My Product Variation Name",
"options": [
{
"id": "5ef4998e0a994e434d6cce88",
"text": null
}
]
}
]
}
]
However, if I use a ProductVariationRepository
and do the fetch one level down, it works perfectly.
[
{
"id": "5ef4998e0a994e434d6cce84",
"name": "My Product Variation Name",
"options": [
{
"id": "5ef4998e0a994e434d6cce88",
"text": "My options value"
}
]
}
]
Is this a bug? Can't you have multi level relationship? Or have I missed something in my configuration ?
Hi,
after upgrading from spring boot 2.5.5 to 2.7.5, relmongo saves the related objects as subdocuments:
class Case{
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.NONE)
@JoinProperty(name = "persons")
private List<Person> persons = new ArrayList<>();
}
class Person{
@Id
String _id;
String name;
String email;
}
Saving the Case, results in this DB entry:
{
"persons" : [
{"_id": "XXX", "name"="Paul", "emai"l; "paul@..."},...
]
}
Loading does not touch the "persons" collection as well!
This behavior started with the upgrade to ne new Spring boot version.
do not scan all documents hierarchy but only mongodb entities
I have manyToOne and oneToMany relationship like
class A {
...
@OneToMany
List<B> b;
@LastModifiedDate
private LocalDateTime lastModifiedDate;
}
class B {
...
@ManyToOne
A a;
}
This fails because the auditing field lastModifiedDate, gets updated (I think) and the save method fails. removing the auditing field works fine.
org.springframework.data.mapping.MappingException: Cannot lookup property @io.github.kaiso.relmongo.annotation.ManyToOne(mappedBy=gists, fetch=LAZY)private com.timecloud.source.entity.pojo.ClassA com.timecloud.gist.entity.ClassB.source on null intermediate! Original path was: source.lastModifiedDate on com.timecloud.gist.entity.ClassB.
Can you support relMongo for spring 3.x
hi good work,
i suggest to add more attributes for collection mapping (exp : orphanRemoval, mappedBy),
there is a bug problem when use bidirection relationship (exp : person -> cars , car -> own person) when persist data there an exception for rerurcive data (spring boot + jackson) because the 2 side off relationship refrences recursivly one to other (person -> list cars & car -> person -> list cars -> ......, son can resole this without loose the the reference of 2 relationship
I have entities similar to this.
public class Parent {
@OneToMany(fetch= FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
@JoinProperty(name="childrens")
private List<Child> childrens;
}
public class Child {
@ManyToOne(mappedBy = "childrens", fetch= FetchType.EAGER)
private Parent parent;
}
I've implemented something like
public class ParentRepository extends MongoRepository<Parent, ObjectId> {
@DeleteQuery( value = "{'property1' : ?0, 'property2' : ?1 }")
void deleteParentByProperties(String property1, String property2);
}
when I do parentRepository.deleteParentByProperties("param1", "param2");
-> It deleted the parent but not the child (Note: this is a custom method implemented with a Query - but still native?)
when I do parentRepository.delete(parent);
-> It deletes the child as well (works as expected). (Note : This is a native method)
Instead of individual parent, I wanted to delete all parent that match a certain condition and avoid doing a fetch query.
Could you kindly tell me if it is possible with relmongo:
Example with mysql:
@ManyToMany(fetch=FetchType.EAGER) @JoinTable(name = "users_roles", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
Thank you in advance.
P.S. Sorry for writing here - haven't found your contact details. I will close issue)
How to update and delete child document using parentId and childId in oneToMany relationship
Update: @PutMapping("/posts/{postId}/comments/{commentId}")
public Comment updateComment(@PathVariable (value = "postId") Long postId,@PathVariable (value =
"commentId"),Long commentId,@requestbody Comment commentRequest) {
// Update Logic - query
}
Delete: @DeleteMapping("/posts/{postId}/comments/{commentId}")
By executing a query to retrieve the parent documents that has a many to one relationship to child documents, relmongo will issue 100 queries to retrieve the child documents when the number of returned parent documents are 100. As the number of documents in mongodb increases, the queries being executed separately can easily affect the performance of the application. Is it possible to load all child documents by 1 queries instead of N queries?
hi
i have one issue (A) and one suggestion (B)
A. with last exemple (car & person), when load person document
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.XXX)
@JoinProperty(name = "cars")
List cars;
in spring data jpa we can resolve this by add : spring.jpa.hibernate.enable_load_lazy_no_trans=true (application.properties) and all work fine, how about spring data mongodb ???
B. orphanRemoval implemnation in @OneToMany
Hello @kaiso Kaiso!
I faced such problem:
I have two models linked via
@OneToOne (fetch = FetchType.EAGER) @JoinProperty (name = "stats").
Everything works fine, but when I try "show collections" in console or view them in mongodb-compass, I see only one - the first (there should be two collections, as I understand it). Please tell me how to display the second collection.
Thank you in advance.
BRGDS
P.S.
example:
"stats": { "_id": "392395918", "_relmongo_target": "FootballMatchStat" }
So I cant find FootballMatchStat collection anywhere
Hello @kaiso
I wanted to design a new logo for relmongo. I think this looks more modern. I just want to help. I can send you a pr if you want. Also, Please tell me if there is a place you want to customize. I will wait for feedback.
Have a nice day!
According to the mapping chapter of mongodb 1.3.3.RELEASE, the _id field can be of any type other than arrays.
https://docs.spring.io/spring-data/mongodb/docs/1.3.3.RELEASE/reference/html/mapping-chapter.html
_7.1.1 How the '_id' field is handled in the mapping layer
MongoDB requires that you have an '_id' field for all documents. If you don't provide one the driver will assign a ObjectId with a generated value. The "id" field can be of any type the, other than arrays, so long as it is unique.
I've forked 3.4.0-RC1 and adapted io.github.kaiso.relmongo.util.ObjectIdReaderCallback to also support Long.
Do you think that is sensible? I guess other types should be supported as well?
I've also had to adapt the mapIdentifier method in io.github.kaiso.relmongo.mongo.DocumentUtils respectively.
I've create the following pull request: #58
If you are happy with this, I will try to adapt it accept any type other than arrays.
Many thanks and happy weekend!
When I create Collection1, all SubCollection are created.
But when I delete Collection1, SubCollection not deleted
@Document
public class Collection1 {
@Id
private String id;
@OneToOne(fetch = EAGER, cascade = ALL)
@JoinProperty(name = "superCollection")
private SuperCollection superCollection;
....
}
@JsonTypeInfo(use = NAME, include = PROPERTY, property = "type", visible = true)
@JsonSubTypes({
@JsonSubTypes.Type(value = SubCollection1.class, name = "subCollection1"),
@JsonSubTypes.Type(value = SubCollection2.class, name = "subCollection2")
})
@Document
public class SuperCollection {
@Id
private String id;
....
}
public class SubCollection1 extends SuperCollection {
private Integer value;
...
}
hi
with version 2.2.1, bug fixed, its works fine with fetch = LAZY.
i not see any implemenation of orphanRemoval in this version
Hi,
we are using a one to many relation from a PersistedCase to a PersistedPerson:
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.NONE) @JoinProperty(name = "offers") private List<PersistedOffer> offers = new ArrayList<>();
Then we add Persons in a specific order and save it. In 20-50% of the cases the order of the Persons lists order has changed when I look into the DB.
Best
Andreas
I found another thing that I think is a bug. In our model we would like to have a one-to-many relationship to another collection but in two different fields. But that seems to screw things up.
In the example below I have two fields on the Offer
class, products
and addons
, referring with a OneToMany relationship to the same collection products
. The products for both fields has been saved earlier and exists in the database.
@Document(collection = "offers")
@TypeAlias(value = "offer")
public class Offer {
@Id
private String id;
private String name;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.NONE)
@JoinProperty(name = "products")
private List<Product> products;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.NONE)
@JoinProperty(name = "products")
private List<Product> addons;
}
@Document(collection = "products")
@TypeAlias(value = "product")
public class Product {
@Id
private String id;
private String name;
}
Below is the data added. I have a ModelMapper
converter that converts the string ids in products
and addons
to real objects before saving. And it works when I remove the relationship to addons
.
{
"name": "My Offer",
"category": "CATEGORY_X",
"subcategory": "SUB_CATEGORY_Y",
"products": [
"5ef5f73d9959571a685ade51"
],
"addons": [
"5ef5f75d9959571a685ade54"
],
"rules": []
}
The result in MongoDB is a document that looks like this. It has saved the product reference from addon into the products field. And addon reference is completely missing.
{
"_id" : ObjectId("5ef5f7ba9959571a685ade56"),
"name" : "My Offer",
"category" : "CATEGORY_X",
"subcategory" : "SUB_CATEGORY_Y",
"_class" : "offer",
"products" : [
{
"_id" : ObjectId("5ef5f75d9959571a685ade54"),
"_relmongo_target" : "products"
}
]
}
Thanks for any help you could provide. It's a great library.
be able to persist a child document when persisting a parent document using the cascade persist type
Hi,
First thanks for the wonderfull plugin.
I have two classes Agency and Country with OneToOne relation
@Document
public class Agency {
@Id
@JsonIgnore
@Getter
private String id;
@Getter @Setter
@Indexed(unique = true)
private String agencyCode;
//The login of the agency
@Getter @Setter
private String login;
//The password of the agency
@Getter @Setter
private String password;
@JsonIgnore
@OneToOne(fetch=FetchType.EAGER)
@JoinProperty(name = "country")
@Getter @Setter
private Country country;
// @OneToMany(fetch=FetchType.EAGER, cascade = CascadeType.PERSIST)
// @JoinProperty(name="mobilemoney")
// private List<MobileMoneyOperator> mobileMoneyService;
/**
* constructor with required parameters
* @param agencyCode
* @param login
* @param password
* @param country
*/
public Agency(String agencyCode, String login, String password, Country country) {
super();
this.agencyCode = agencyCode;
this.login = login;
this.password = password;
this.country = country;
}
}
public class Country {
@Id
@JsonIgnore
private String id;
@Indexed(unique = true)
private String countryCode;
//The name of the country
@Indexed(unique = true)
private String name;
@OneToOne(mappedBy = "country", fetch = FetchType.EAGER)
private Agency agency;
}
My use case :
Problem:
When I create a country with an agency to null, the first time it is good. The 2nd time, I got the error
Caused by: com.mongodb.MongoWriteException: E11000 duplicate key error collection: gara-cash-transaction.country index: agency.agencyCode dup key: { agency.agencyCode: null }
at com.mongodb.client.internal.MongoCollectionImpl.executeSingleWriteRequest(MongoCollectionImpl.java:1055) ~[mongodb-driver-3.11.1.jar:na]
at com.mongodb.client.internal.MongoCollectionImpl.executeInsertOne(MongoCollectionImpl.java:498) ~[mongodb-driver-3.11.1.jar:na]
at com.mongodb.client.internal.MongoCollectionImpl.insertOne(MongoCollectionImpl.java:482) ~[mongodb-driver-3.11.1.jar:na]
at com.mongodb.client.internal.MongoCollectionImpl.insertOne(MongoCollectionImpl.java:476) ~[mongodb-driver-3.11.1.jar:na]
This is probably do to the fact that I added in country
@OneToOne(mappedBy = "country", fetch = FetchType.EAGER)
private Agency agency;
How is it possible to create all countries first with Agency to null, then to add for each country an agency ?
null is detected as key, in agency.agencyCode, but I don't want him to create cascade.
E11000 duplicate key error collection: gara-cash-transaction.country index: agency.agencyCode dup key: { agency.agencyCode: null }
Thanks in advance.
I have a problem with some tests
I use
@RunWith(SpringRunner.class)
@WebMvcTest(UtilisateursRest.class)
@AutoConfigureMockMvc(addFilters = false)
class UsersRestTest {
The error :
Failed to load ApplicationContext
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132)
...
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mongoTemplate$RelMongo$OK$RLMIndexCreator': Cannot resolve reference to bean 'mongoTemplate' while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'mongoTemplate' available
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:342)
....
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'mongoTemplate' available
For other tests, its work fine :
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = MOCK)
@TestMethodOrder(OrderAnnotation.class)
@AutoConfigureMockMvc
class UserRestIT {
and
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
When creating some "app" entities, and assigning a few to a user entity,
<app1 = new Application(...), app2=new Application(...), app3 =... omitted for brevity>
User user1 = User.builder()
.uuid("uuid1")
.name("Don Johnson")
.app(app1)
.app(app3)
.build();
appRepo.save(app1);
appRepo.save(app2);
appRepo.save(app3);
userRepo.save(user1);
My user entity:
@Data
@Document
@Builder
public class User {
@Id
private String uuid;
private String name;
@OneToMany(fetch=FetchType.EAGER)
@JoinProperty(name="apps")
@Singular
private Set<Application> apps;
}
My app entity:
@Data
@Document
@Builder
public class Application {
@Id
//@NotBlank
//@Length(max =250)
private String uuid;
//@NotBlank
@Length(max=50)
private String name;
private String version;
private Date updatedAt;
Without the @EnableRelationalMongo annotation, I see the apps are persisted as expected, using spring data rest I see my 3 apps at the /apps endpoint, and at the /users endpoint, I see user 1 has apps "app1" and "app3" associated with it.
When I enable this framework by adding the @EnableRelationalMongo annotation, the following exception is encountered upon hitting the /users endpoint. (It seems that the afterLoad() logic is querying for the related entities, but the _ids of the user's associated apps generated by the framework do not match the _ids of the apps actually persisted by spring.
java.lang.IllegalArgumentException: Collection must not be null or empty!
at org.springframework.util.Assert.hasText(Assert.java:276) ~[spring-core-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at io.github.kaiso.relmongo.mongo.DatabaseLoader.getDocumentsById(DatabaseLoader.java:28) ~[relmongo-2.0.0-RC1.jar:na]
at io.github.kaiso.relmongo.mongo.PersistentRelationResolver.resolveOnLoading(PersistentRelationResolver.java:54) ~[relmongo-2.0.0-RC1.jar:na]
at io.github.kaiso.relmongo.events.listener.MongoEventListener.onAfterLoad(MongoEventListener.java:46) ~[relmongo-2.0.0-RC1.jar:na]
at org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener.onApplicationEvent(AbstractMongoEventListener.java:56) ~[spring-data-mongodb-2.0.5.RELEASE.jar:2.0.5.RELEASE]
at org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener.onApplicationEvent(AbstractMongoEventListener.java:31) ~[spring-data-mongodb-2.0.5.RELEASE.jar:2.0.5.RELEASE]
I'm using spring boot 2.0.2 managed dependencies and
<dependency>
<groupId>io.github.kaiso.relmongo</groupId>
<artifactId>relmongo</artifactId>
<version>2.0.0-RC1</version>
</dependency>
Using:
id("org.springframework.boot") version "2.3.4.RELEASE"
id("io.spring.dependency-management") version "1.0.10.RELEASE"
implementation("io.github.kaiso.relmongo:relmongo:3.4.0")
implementation("org.springframework.boot:spring-boot-starter-data-mongodb")
implementation("org.springframework.boot:spring-boot-starter-data-mongodb-reactive")
Having the following class setup:
@Document("persons")
data class Person(
@Id
val id: String,
val name: String,
@OneToMany(fetch=FetchType.EAGER, cascade=CascadeType.PERSIST)
@JoinProperty(name = "cars")
val cars: List<Car>
)
@Document("cars")
data class Car(
@Id
val id: String,
val name: String,
)
@Repository
interface PersonRepository : MongoRepository<Person, String>
And using it as followed in a unit test:
@Test
fun `experiment`() {
val car = Car("001", "BWM")
val person = Person("101", "Peter", listOf(car))
personRepository.save(person)
val foundPerson = personRepository.findAll()[0]
assertThat(foundPerson.cars[0].name).isEqualTo("101")
}
The result is always an exception:
Failed to instantiate com.alemannigame.backend.persistence.mongodb.document.Car using constructor fun <init>(kotlin.String, kotlin.String): com.alemannigame.backend.persistence.mongodb.document.Car with arguments 001,null
org.springframework.data.mapping.model.MappingInstantiationException: Failed to instantiate com.alemannigame.backend.persistence.mongodb.document.Car using constructor fun <init>(kotlin.String, kotlin.String): com.alemannigame.backend.persistence.mongodb.document.Car with arguments 001,null
at org.springframework.data.mapping.model.ClassGeneratingEntityInstantiator$EntityInstantiatorAdapter.createInstance(ClassGeneratingEntityInstantiator.java:240)
at org.springframework.data.mapping.model.ClassGeneratingEntityInstantiator.createInstance(ClassGeneratingEntityInstantiator.java:87)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:344)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:317)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.readCollectionOrArray(MappingMongoConverter.java:1119)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.readValue(MappingMongoConverter.java:1578)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter$MongoDbPropertyValueProvider.getPropertyValue(MappingMongoConverter.java:1478)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter$AssociationAwareMongoDbPropertyValueProvider.getPropertyValue(MappingMongoConverter.java:1527)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter$AssociationAwareMongoDbPropertyValueProvider.getPropertyValue(MappingMongoConverter.java:1490)
at org.springframework.data.mapping.model.PersistentEntityParameterValueProvider.getParameterValue(PersistentEntityParameterValueProvider.java:71)
at org.springframework.data.mapping.model.SpELExpressionParameterValueProvider.getParameterValue(SpELExpressionParameterValueProvider.java:49)
at org.springframework.data.mapping.model.ClassGeneratingEntityInstantiator$EntityInstantiatorAdapter.extractInvocationArguments(ClassGeneratingEntityInstantiator.java:262)
at org.springframework.data.mapping.model.ClassGeneratingEntityInstantiator$EntityInstantiatorAdapter.createInstance(ClassGeneratingEntityInstantiator.java:235)
at org.springframework.data.mapping.model.ClassGeneratingEntityInstantiator.createInstance(ClassGeneratingEntityInstantiator.java:87)
I am using below structure
class ProfileEntity{
.......
@OneToMany(fetch=FetchType.EAGER, cascade=CascadeType.PERSIST)
@JoinProperty(name="emailNotificationsId")
private List emailNotifications;
}
public class EmailNotificationsEntity {
@Id
private Integer emailNotificationsId;
@Field(name="email_notifications_name")
private String name;
@ManyToOne(mappedBy = "emailNotifications")
private List<ProfileEntity> profiles;
}
For this structure i am getting below error while fetching ProfileEntity data
io.github.kaiso.relmongo.exception.RelMongoProcessingException: unable to set mappedBy child object Can not set java.util.List field com.test.core.profile.entity.EmailNotificationsEntity.profiles to com.test.core.profile.entity.ProfileEntity
I'll take the example you have posted in the wiki: (Person and Cars)
class Person{
...
@OneToMany(fetch= FetchType.LAZY, cascade = CascadeType.ALL)
@JoinProperty(name="cars")
private List<Car> cars = new ArrayList<>();
public addCar(Car c){
car.setPerson(this);
this.getCars().add(car);
}
}
class Cars{
...
@ManyToOne(mappedBy = "cars", fetch= FetchType.EAGER)
private Person owner;
}
Person p = new Person();
Car c = new Car();
p.addCar(car)
p.save();
//saving the 2nd car overrides the 1st car values
Car car2 = new Car();
p.add(car2);
p.save();
I've seen instances where saving car2
creates null
(default values) of the class. Am I doing something wrong?
Apparently, when this.getCars()
is called it loads the first car with the correct id but all of the other properties are empty/class defaults (and not the saved value).
I was working on relmongo v3.0.0
. Recently, I realized that there were newer versions avaialble, so I decided to upgrade to v3.2.0
. However, one of the test cases that was passing previously started to fail on me.
Code
Criteria expression = Criteria.where("expirationDate").lt(LocalDateTime.now());
Query query = new Query().addCriteria(expression);
return mongoTemplate.remove(query, UserPasswordReset.class).wasAcknowledged();
The above code was/is working with v3.0.0
., but not with versions greater than v3.0.0.
(v3.0.1, v3.1.0 and v3.2.0).
[Note :: I played around with other mongoTemplate
methods like find
and it seems to work with all versions. Also, I have similar codes using query and criterion that is based on String
and remove
method, and those are working without any issues on all versions.]
The associated class
@Getter
@ToString
@Document(collection = "passwordResets")
@EntityListeners(AuditingEntityListener.class)
public class UserPasswordReset {
@Id
private ObjectId id;
@NotNull
private String email;
private String token = UUID.randomUUID().toString();
private LocalDateTime expirationDate = LocalDateTime.now();
@CreatedDate
private LocalDateTime createdDate;
// overloaded constructor
public UserPasswordReset(String email){ this.email = email; }
}
Error message
org.springframework.data.mapping.MappingException: Expected to read Document Document{{$lt=Mon Mar 16 14:30:08 CDT 2020}} into type class java.time.LocalDateTime but didn't find a PersistentEntity for the latter!
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:244)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.readValue(MappingMongoConverter.java:1493)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter$MongoDbPropertyValueProvider.getPropertyValue(MappingMongoConverter.java:1391)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.readProperties(MappingMongoConverter.java:380)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.populateProperties(MappingMongoConverter.java:297)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:277)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:247)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:196)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:192)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:80)
at io.github.kaiso.relmongo.events.callback.PersistentPropertyCascadingRemoveCallback.<init>(PersistentPropertyCascadingRemoveCallback.java:50)
at io.github.kaiso.relmongo.events.processor.RelMongoProcessor.onBeforeDelete(RelMongoProcessor.java:110)
at org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener.onApplicationEvent(AbstractMongoEventListener.java:68)
at org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener.onApplicationEvent(AbstractMongoEventListener.java:31)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:402)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:359)
at org.springframework.data.mongodb.core.MongoTemplate.maybeEmitEvent(MongoTemplate.java:2276)
at org.springframework.data.mongodb.core.MongoTemplate$9.doInCollection(MongoTemplate.java:1694)
at org.springframework.data.mongodb.core.MongoTemplate$9.doInCollection(MongoTemplate.java:1689)
at org.springframework.data.mongodb.core.MongoTemplate.execute(MongoTemplate.java:545)
at org.springframework.data.mongodb.core.MongoTemplate.doRemove(MongoTemplate.java:1689)
at org.springframework.data.mongodb.core.MongoTemplate.remove(MongoTemplate.java:1677)
at org.springframework.data.mongodb.core.MongoTemplate.remove(MongoTemplate.java:1670)
at com.timecloud.user.repository.UserPasswordResetCustomRepositoryImpl.deleteAllInactive(UserPasswordResetCustomRepositoryImpl.java:45)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
While performing a sample test of relmongo in my project I am facing the given issue:
java.lang.RuntimeException: java.lang.NoSuchMethodError: com.krakken.learningmongo.models.Person$$EnhancerByCGLIB$$af5ebd31: method 'void <init>()' not found
at org.springframework.data.repository.core.support.RepositoryMethodInvoker$RepositoryFragmentMethodInvoker.lambda$new$0(RepositoryMethodInvoker.java:281)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:170)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:158)
at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:516)
at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:285)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:628)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:168)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:143)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:70)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.data.mongodb.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:158)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:220)
at jdk.proxy2/jdk.proxy2.$Proxy114.findById(Unknown Source)
at com.krakken.learningmongo.repository.PersonRepositoryTests.testOneToManyMappingBetweenCarAndPerson(PersonRepositoryTests.java:71)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
Caused by: java.lang.NoSuchMethodError: com.krakken.learningmongo.models.Person$$EnhancerByCGLIB$$af5ebd31: method 'void <init>()' not found
at com.krakken.learningmongo.models.Person$$EnhancerByCGLIB$$af5ebd31.newInstance(<generated>)
at io.github.kaiso.relmongo.mongo.PersistentRelationResolver.lazyLoader(PersistentRelationResolver.java:55)
at io.github.kaiso.relmongo.events.callback.PersistentPropertyPostLoadingCallback.doWith(PersistentPropertyPostLoadingCallback.java:103)
at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:728)
at org.springframework.util.ReflectionUtils.doWithFields(ReflectionUtils.java:707)
at io.github.kaiso.relmongo.events.processor.RelMongoProcessor.onAfterConvert(RelMongoProcessor.java:127)
at io.github.kaiso.relmongo.events.processor.RelMongoProcessor.onApplicationEvent(RelMongoProcessor.java:86)
at io.github.kaiso.relmongo.config.RelMongoBeanPostProcessor$RelMongoEventPublisher.publishEvent(RelMongoBeanPostProcessor.java:84)
at org.springframework.data.mongodb.core.EntityLifecycleEventDelegate.publishEvent(EntityLifecycleEventDelegate.java:53)
at org.springframework.data.mongodb.core.MongoTemplate.maybeEmitEvent(MongoTemplate.java:2363)
at org.springframework.data.mongodb.core.MongoTemplate$ReadDocumentCallback.doWith(MongoTemplate.java:3284)
at org.springframework.data.mongodb.core.MongoTemplate.executeFindOneInternal(MongoTemplate.java:2874)
at org.springframework.data.mongodb.core.MongoTemplate.doFindOne(MongoTemplate.java:2536)
at org.springframework.data.mongodb.core.MongoTemplate.findOne(MongoTemplate.java:817)
at org.springframework.data.mongodb.repository.support.SimpleMongoRepository.findById(SimpleMongoRepository.java:127)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:351)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker$RepositoryFragmentMethodInvoker.lambda$new$0(RepositoryMethodInvoker.java:277)
... 21 more
Here are my models
Car.java
package com.krakken.learningmongo.models;
import io.github.kaiso.relmongo.annotation.ManyToOne;
import lombok.Builder;
import lombok.Data;
import org.bson.types.ObjectId;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
@Document(collection = "car")
@Data
public class Car {
@Id
private String id;
@Indexed(unique = true)
private int identifier;
public Car(int identifier) {
this.identifier = identifier;
}
private String manufacturer;
private Color color;
@ManyToOne(mappedBy = "cars")
private Person Owner;
}
Person.java
package com.krakken.learningmongo.models;
import io.github.kaiso.relmongo.annotation.CascadeType;
import io.github.kaiso.relmongo.annotation.FetchType;
import io.github.kaiso.relmongo.annotation.JoinProperty;
import io.github.kaiso.relmongo.annotation.OneToMany;
import lombok.*;
import org.bson.types.ObjectId;
import org.springframework.data.mongodb.core.mapping.Document;
import java.util.List;
@Document(collection = "person")
@Data
@Builder
public class Person {
private ObjectId id;
private String name;
private String email;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinProperty(name = "carsrefs")
@Singular
private List<Car> cars;
}
and I have added the relMongo annotation like this,
package com.krakken.learningmongo;
import io.github.kaiso.relmongo.config.EnableRelMongo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.mongodb.config.EnableMongoAuditing;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
@SpringBootApplication
@EnableRelMongo(mongoTemplateRef = "mongoTemplate")
@EnableMongoAuditing
public class LearningMongoApplication {
public static void main(String[] args) {
SpringApplication.run(LearningMongoApplication.class, args);
}
}
While performing the given series of test, I am facing the above issue.
package com.krakken.learningmongo.repository;
import com.krakken.learningmongo.config.MongoSpringConfiguration;
import com.krakken.learningmongo.models.Account;
import com.krakken.learningmongo.models.Car;
import com.krakken.learningmongo.models.Color;
import com.krakken.learningmongo.models.Person;
import com.mongodb.MongoConfigurationException;
import io.github.kaiso.relmongo.util.RelMongoConstants;
import org.bson.Document;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.util.Arrays;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.*;
@ActiveProfiles("test")
@ExtendWith(SpringExtension.class)
@SpringBootTest
public class PersonRepositoryTests {
@Autowired
private PersonRepository personRepository;
@Autowired
private CarRepository carRepository;
@Autowired
private MongoOperations mongoOperations;
@BeforeEach
void clearDatabase() {
personRepository.deleteAll();
carRepository.deleteAll();
}
@Test
@DisplayName("Test one to many mapping between car and persons")
void testOneToManyMappingBetweenCarAndPerson() {
Car car1 = new Car(1);
car1.setColor(Color.BLUE);
car1.setManufacturer("BMW");
Car car2 = new Car(2);
car2.setColor(Color.RED);
car2.setManufacturer("BMW");
car1 = carRepository.save(car1);
car2 = carRepository.save(car2);
Person person = Person.builder()
.name("Dave")
.email("[email protected]")
.cars(Arrays.asList(new Car[]{car1, car2}))
.build();
person = personRepository.save(person);
Optional<Car> foundCarOptional = carRepository.findById(car1.getId());
assertTrue(foundCarOptional.isPresent());
Car foundCar = foundCarOptional.get();
assertNotNull(foundCar.getOwner());
assertEquals(foundCar.getOwner().getId(), person.getId());
Optional<Person> foundPersonOptional = personRepository.findById(person.getId().toString());
assertTrue(foundPersonOptional.isPresent());
Person foundPerson = foundPersonOptional.get();
assertEquals(2, foundPerson.getCars().size());
}
}
Can you tell me which changes I have to make in order to make it work?
I am in ubuntu 23.04.
Hi Kaiso!
I'm getting OutOfMemory errors in my application and after analysing the heap dump, it looks like it may be due to the close() method of PersistentPropertyPostLoadingCallback never being called.
I do have to mention though, that I am running on a fork... which has a feature which you decided not to include (#60). So maybe it will only ever be me having this problem, as I instantiate an instance of PersistentPropertyPostLoadingCallback within PersistentPropertyPostLoadingCallback itself.
Thought I would mention it just in case though.
Many thanks again for your great work, keep it up!
Hi All,
Issue:
For enabling transactions on MongoDB 4.0 it is required to use AbstractConfiguration. When I add this configuration RelMongo stops working.
Implementation:
public class MongoTransactionConfig extends AbstractMongoConfiguration {
@Bean
MongoTransactionManager transactionManager(MongoDbFactory dbFactory) {
return new MongoTransactionManager(dbFactory);
}
@Value("${spring.data.mongodb.host}")
private String host;
@Value("${spring.data.mongodb.port}")
private Integer port;
@Value("${spring.data.mongodb.database}")
private String database;
@Override
protected String getDatabaseName() {
return database;
}
@Override
@Bean
public MongoClient mongoClient() {
return new MongoClient(host, port);
}
}
PS: Great dependency, I love how it smooth it is.
Thanks,
Rafael
I have a scenario where an object has an embedded object (field) which itself is persisted as part of the outer @document but annotated fields within the embedded object should be scanned for @OnetoOne and @OneToMany annotations.
Example:
ArticleDTO {
@Id
private Long id;
@OneToOne(...)
@JoinProperty(...)
private OtherDTO other;
private MetaDTO meta;
}
MetaDTO {
@Id
private Long id;
@OneToOne(...)
@JoinProperty(...)
private FooDTO foo;
}
Currently, the annotations on the FooDTO field in MetaDTO would never be read.
How about a @nested annotation, which would then perform the same functionality on the MetaDTO field?
<dependency>
<groupId>io.github.kaiso.relmongo</groupId>
<artifactId>relmongo</artifactId>
<version>1.0.0-RC2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency> //Using Spring Boot 2.0.2 dependency management
public interface UserRepository extends CrudRepository<User,String> {
}
public interface ApplicationRepository extends CrudRepository<Application,String> {
}
@Data
@Document
@Builder
public class User {
@Id @NotBlank
private String id;
private String name;
@OneToMany(fetch=FetchType.EAGER)
@Singular
private Set<Application> apps;
}
@Data
@Document
@Builder
public class Application {
@Id
//@NotBlank
@Length(max =250)
private String uuid;
//@NotBlank
@Length(max=50)
private String name;
private String version;
private Date updatedAt;
//@NotBlank
@Length(max=500)
private String summary;
@URL
//@NotBlank
private String icon;
private String description;
@Valid
@Singular
private List<AccessUrl> urls;
@Valid
private Support support;
}
@Autowired
private ApplicationRepository appRepo;
@Autowired
private UserRepository userRepo;
...
appRepo.save(app1);
appRepo.save(app2);
appRepo.save(app3);
userRepo.save(user1);
java.lang.NoSuchMethodError: org.springframework.data.mongodb.core.mapping.event.BeforeSaveEvent.getDBObject()Lcom/mongodb/DBObject;
at ****io.github.kaiso.relmongo**.events.listener.MongoEventListener.onBeforeSave**(MongoEventListener.java:53) ~[relmongo-1.0.0-RC2.jar:na]
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.