I am making a simple CRUD application using Spring boot and MongoDB, the problem that I am facing is that I don't know how to define the model classes.
My application should be like this:
A site has some characteristics such as an ID, region, city, ... and contains 4 parts (cellulars) that each has its own characteristics. Any help would be appreciated.
This is what I have so far:
public class Site {
#Id
String siteId;
String projectPhase;
String region;
String city;
String siteName;
String newSiteName;
String clusterName ;
String longitude ;
String lattitude ;
#OneToMany(mappedBy = "siteId")
List L;
What I want to know is how do I associate another class inside this one.
Annotations like #OneToMany are typically used within JPA-context, and are unnecessary when using Spring Data MongoDB. This is also mentioned by the documentation:
There’s no need to use something like #OneToMany because the mapping framework sees that you want a one-to-many relationship because there is a List of objects.
You have a few options when you want to define one-to-many relations when using MongoDB. The first of them is to define them as embedded objects within the same document:
#Document
public class Site {
#Id
private String id;
private String city;
private String region;
private List<Part> cellulars;
}
public class Part {
private String characteristic1;
private String characteristic2;
}
This means that the parts do not exist on their own, so they don't need their own ID either.
Another possibility is to reference to another document:
#Document
public class Site {
#Id
private String id;
private String city;
private String region;
#DBRef
private List<Part> cellulars;
}
#Document
public class Part {
#Id
private String id;
private String characteristic1;
private String characteristic2;
}
In this case, parts are also separate documents, and a site simply contains a reference to the part.
Related
I am trying to understand how the two different annotations of #Indexed and #Field differ while defining a model in Java Spring Boot.
public class Notation {
#Id
private String id;
#Field("value")
private String value;
#Field("description")
private String description;
#Field("frequency")
private int frequency;
}
public class Notation {
#Id
private String id;
#Indexed("value")
private String value;
#Indexed("description")
private String description;
#Field("frequency")
private int frequency;
}
My use case is to finally implement a search from the repository based on both value and description fields, so it would be good to get an idea of how the data is structured in the two and what are the various options one can use from these annotations.
#Indexed annotation is will add an index that on that field in your mongo server. It takes an optional string parameter, which will be the index name and nothing to do with the field name. You should have only those fields indexed which will be used for filtering out documents.
#Field is used if you want to have different names in your java code and MongoDB collection.
For eg.
#Field("desc")
private String description;
In this case, in your MongoDB collection, you will find field name as "desc" while in your java code you will be referencing it as "description"
#Field("description")
private String description;
In the above case, there is no need for using #Field annotation
Background:
I am trying to model a many-to-many relationship using the embedded document model.
The reason behind choosing mongodb is because the schema is dynamic as the platform deals with various products and services.
The application when logged in by an user bootstraps all the information of a user. But, all the queries such as update,search are majorly done on the products and services associated with users on the platform.
Problem Statement:
#Getter
#Setter
#ToString(exclude = { "id", "password" })
#Document(collection = "users")
public class User implements Serializable {
#Id
private ObjectId id;
#Indexed(unique = true)
private String username;
private String password;
private String email;
private String mobile;
private Sex sex;
private List<String> tags;
}
public class Product {
#Id
private String id;
private String name;
private double price;
private List<User> users;
}
public class Service{
#Id
private String id;
private String name;
private double price;
private List<User> users;
}
Initially i thought of making users as embedded documents within products and services. The reason behind choosing the embedded document design is to avoid multiple queries during the search.
But, I also realized that when a user logs in to the application i need to have all the user related information which needs to be bootstrapped. The design seems to be getting complicated.
I would like to understand if this scenario could be handled in a better way. Anyone who has already solved this situation?
The queries i would like to perform are
Find:
db.products.find({"name": /.*m.*/})
Update:
.update(Products:{$elemMatch:{Bag:"charollette"}}, {$set: {'Products.$.Name':"Charollette blue"}});
Insert:
db.products.insertOne( { item: "card", qty: 15 } );
I'm building an application with Google App Engine. I'm using Objectify for Datastore persistence. I have two POJO class.
#Entity
public class Book
{
#Id private Long id;
private String name;
private String isbn;
private String author;
}
and
#Entity
public class Person {
#Id private String email;
private String password;
private String name;
private List<Book> myBooks;
}
A person can contain many books but book only belongs to one person. Currently I'm saving data like this.
//data from Front-end
Person p = new Person(email, password, name);
PersonDAO dao = new PersonDAO();
dao.save(p);
//...
//data from Front-end
Book b = new Book(name, author, isbn);
BookDAO daoBook = new BookDAO();
daoBook.save(b);
//...
Person q = dao.load(email);
q.addBook(b);
dao.save(q);
ObjectifyService ofy() with methods are implemented in DAO classes.
It's ok my implementation? How can I optimize the relationship? Every time that I need create a book this is saved like Entity but I need the relationship with a person, therefore I'm saving book twice. I've seen implementantions with Key, Ref #Load tags but I don't know how are working them.
Besides, Person POJO has a Date field. will It be saved normally?
It has being quite a while since I wrote this code, but here it goes:
#Entity
public class Book {
#Id
private Long id;
#Parent
#ApiResourceProperty(ignored = AnnotationBoolean.TRUE)
private Key<User> user;
private String author;
private String isbn;
private String name;
}
Take a look at Udacity Conference Central for full example. It is the final project of Developing Scalable Apps in Java
with Google App Engine, by Udacity.
I've used Hibernate / JPA in the past, now using a combination of Spring JDBC and MyBatis.
With JPA/ Hibernate if you had a Customer, which had an address you would have a domain structure similar to code below. (minus all the annotations / config / mappings).
Does this still make sense when using JDBC or MyBatis. This is composition domain design from what I know, has-a, belongs-to, etc. However most examples I've seen of JDBC code they have domain object that bring back the IDs rather than collection, or flatten the data. Are there any performance benefits from either approach, maintainability, etc. Having worked with JPA first I'm not sure what the JDBC way of doing things are.
public class Customer {
private Long id;
private String userName;
private String password;
private String firstName;
private String lastName;
private Collection<Address> addresses
...
}
public class Address {
private Long id;
private String streetAddress1;
private String streetAddress2;
private String city;
private State state;
private String postalCode;
}
public class State {
private Long id;
private String code;
private String name;
private Country country;
}
public class Country {
private Long id;
private String code;
private String name;
}
I come across an example and here was one of their classes.
public class Question {
private long questionId;
private long categoryId;
private long userId;
private long areaId;
private String question;
private String verifyKey;
private Date created;
private User user;
private List<Answer> answers;
private long answerCount;
private String name;
// getters and setters omited...
}
Why would you fetch the userId, areaId, and categoryId instead of actually fetching the associated object? The ID is likely of no use to the front end user, I suppose you could use the ID to issue another query to fetch additional data, but seems inefficient making another round trip to the database.
You can look at this domain object as a "footprint" of database table. In your example, userId, areaId and categoryId from Question are most likely foreign keys from corresponding tables. You could never need full object data in the moment of Question creation and retrieve it later with separate db request. If you fetch all associated objects at once, you will hit at least one additional table per object (by join-s or subselect-s). Moreover, that's actually the same that Hibernate does. By default, it loads domain object lazily and hits database again if uninitialized associated object is needed.
At that time, it is better to fetch those objects that a domain object can't exist without. In your example, Question and List are coupled.
Of course, if you need user, or category, or any other associated object again in some another place of application (assume the reference to previously retrieved object has been lost), you will hit the database with same query. It should be done and could seem inefficient, because both plain JDBC and SpringJDBC have no intermediate caching unlike Hibernate. But that's not the purpose JDBC was designed for.
I have a composite object that I wish to store in mongodb (using spring annotations). The object is as follows:
#Document(collection="person")
class Person {
#Id
private String id;
private Address address;
private String name;
}
and the composite class Address:
#Document
class Address {
#Indexed
private Long countryId;
private String street;
#Indexed
private String city
}
I need both country and city to be indexed as part of the person collection. Alas, no index is created for them. Any ideas how to create the index?
I have tried the following which works but is not elegant:
#Document(collection="person")
#CompoundIndexes({
#CompoundIndex(name = "countryId", def = "{'address.countryId': 1}")
})
class Person {
You can set up multiple secondary indexes, if you wish. This would be a good place to start.