MongoDB how to load two attributes of reference document using morphia - java

How to load two attributes of reference document/entity using morphia
I have a Class Person and School like this
person class
#Entity
public class Person {
#Id private ObjectId id;
private String name;
#Embedded private PersonEducation schoolInfo;
}
#Embedded
public class PersonEduction {
#Reference private School school;
private String year;
private String degree;
}
School Class
#Entity
public class School {
#Id private ObjectId id;
private String name;
private String address;
private String description;
}
How I can get id and and name fields of School in Person class
example
When i want to person
Person person = datastore.find(Person.class).field("name").equals("xyz").get();
person.gerSchoolInfo();
Response (Not want all School class fields)
{school:{_id:ObjectId("4fcef3e20364a375e7631fb0"), name:"SchoolA"}, year:"1990", degree:"MBA" }
and If I query school where _id=ObjectId("4fcef3e20364a375e7631fb0"), I get all School fields
{_id:ObjectId("4fcef3e20364a375e7631fb0"), name:"xyz", address="some add", description="some desc"}

Instead of using #Reference you should use
key<School> school;
and use custom query to load it.
datastore.createQuery(School.class).retrivedFields(true, "id","name");

To give an alternative to mtariq, replace
#Reference private School school;
with
private ObjectId schoolId;
and fetch it yourself. However since your School class is so simple I think you'd be better off using Lazy loading, so:
#Reference #Lazy private School school;
This will only load the school object when/if it is referenced.

Related

How to deserialize Json with a nested array of objects in a simple Spring Boot application

The Json POST request looks like this:
{
'title':'Star Wars: The Empire Strikes Back',
'description':'Darth Vader is adamant about turning Luke Skywalker to the dark side.',
'actors':[
{
'lastName':'Ford',
'name':'Harrison'
},
{
'lastName':'Hamill',
'name':'Mark'
}
]
}
So my Spring Boot Application just wants to store this whole json as a "Film" class and inside it has an inline array of "Actors". Here is the Film model:
#Entity
public class Film {
#Id
#GeneratedValue
private long id;
private String title;
private String description;
private ArrayList<Actor> actors = new ArrayList<>();
I have a separate entity for the Actor that looks similar:
#Entity
public class Actor {
#Id
#GeneratedValue
private long id;
private String name;
private String lastName;
Finally, I am using the RequestBody Annotation in the PostMapping in the Controller:
#PostMapping(value= "/api/film")
#ResponseStatus(HttpStatus.CREATED)
public Film addFilm(#RequestBody Film film) {
service.createFilm(film);
return film;
The problem is I always get the java.io.NotSerializableException that Actor cannot be serialized. I tried making Actor a Static inline class but that did not change anything. Anyone have an idea what is wrong here ?
Your Actor class needs to implement Serializable.
#Entity
public class Actor implements Serializable{
#Id
#GeneratedValue
private long id;
private String name;
private String lastName;

Modelling optional one to many relationship - should I use inheritance?

I am trying to model a weather service that supports multiple locations. My application has 3 entities:
Location - information about the Location
Weather (includes location id) - A single hour of weather data
LocationWeather - Subclass of Location containing a List of Weather
I want Location to sometimes exist as a distinct entity from Weather. That way I can expose CRUD operations on the Location object without carrying the bloat of all of its weather data. However, I still want to satisfy the primary use case of returning weather for a given location, that's why LocationWeather exists.
Can what I want to do be done with inheritance? I've tried
#Entity
#Table(name="location")
#Inheritance(strategy = InheritanceType.JOINED)
public class Location {
but my subclass (LocationWeather) doesn't directly associate with a table. Should I move my List of Weather up to the Location object and somehow mark it as optional?
Location.java
#Entity
#Table(name="location")
public class Location {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="location_id")
private int id;
#Column(name="name")
private String name;
Weather.java
#Entity
#IdClass(WeatherId.class)
#Table(name="weather")
public class Weather {
#Id
#Column(name="location_id")
private int locationId;
#Id
#Column(name="time")
private Date time;
#Column(name="temperature")
private Double temperature;
LocationWeather.java
#Entity
public class LocationWeather extends Location{
#ElementCollection
#CollectionTable(name="weather", joinColumns= {#JoinColumn(name="location_id")})
#Column(name="weather")
private List<Weather> weather;
Figured it out. I was googling the wrong things. I should have been searching for "2 entities 1 table"
I was able to solve the issue by creating a #MappedSuperclass and creating Location and LocationWeather as a subclass of it.
Now I have:
MappedLocation.java
#MappedSuperclass
public class MappedLocation {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="location_id")
private int id;
#Column(name="name")
private String name;
Location.java
#Entity
#Table(name="location")
public class Location extends MappedLocation {
}
LocationWeather.java
#Entity
public class LocationWeather extends MappedLocation{
#ElementCollection
#CollectionTable(name="weather", joinColumns= {#JoinColumn(name="location_id")})
#Column(name="weather")
private List<Weather> weather;
More info: https://thoughts-on-java.org/hibernate-tips-map-multiple-entities-same-table/

JPA: How to map only one property from another entity

Let's say I have two entities:
#Entity
public class Phone {
#Id
private Long id;
private String number;
}
#Entity
public class Person {
#Id
private Long id;
private String name;
}
The relationship between a person and a phone is one to one.
How could I access only the phone's number in the Person entity mapped by the phone's id
#Entity
public class Person {
#Id
private Long id;
private String name;
// ???
private String phoneNumber;
}
The reason for not mapping the whole entity is because in some more realistic entities there are too many properties.
I don't think you can, but something like this might be acceptable:
public class Person {
#OneToOne
#JoinColumn(name = "phone_id")
private Phone phone;
public String getPhoneNumber() {
return phone.getNumber();
}
}
Although you have mapped the whole object, not just the single property, you have only exposed the single property you want. The other stuff is hidden.
Alternatively, do it at the DB layer using a View:
create view person_with_phone as
select p.id, p.name,f.number
from person p
join phone f on f.id=p.phone_id
and then have an entity class to match the view. You'll need to turn off schema creation in your JPA implementation.

How can I optimize Objectify relationships?

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.

Indexing composite object in spring mongodb

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.

Categories