I am looking to put a complex model into Hazelcast to use it as the data tier of an application with MapStore implementations rendering the actual objects to the database. So for example, lets say we have the following noxiously common model where I have stripped out getters and setters for brevity:
class Customer {
public int id;
public String name;
public Address address;
}
class Address {
public int id;
public String street;
public string city;
public String state;
public String zip;
}
class InterestGroup {
public int id;
public String name;
public List<Customer> customers;
}
This is a model that I want to store in the database but I also want to map into Hazelcast. Furthermore lets say that I want customers to share addresses such that if the address changes for one, it will change for all customers with that address.
I can write MapStore classes to read this information out of the database and even give each object a primary key to use as a map key. What I am having trouble with is setting up navigation within the map between entities. Lets say I obtain a customer and want to navigate to the address of that customer and then get all customers that use that address.
If I load customers and addresses into a map, I dont want to embed all customers in an address nor do I want to embed the address in each customer. I want to navigate transparrently from the customer to the address. Is there a means by which I could do this in hazelcast without breaking the dynamics of a nested object but while allowing addresses to live in another map? The situation is similar for interest groups. If I embed all customers in an interest group then I am duplicating data all over especially if the customer is in several interest groups.
To accomplish this without duplication all over do I have to compromise the object structure of my entities?
Thanks in advance.
If you know how to build the address_key for the address Hazelcast map you can implement HazecastInstanceAware to your model classes and build some kind of "lazy fetch" using getters to retrieve the address. Does that make sense to you? :)
Related
I have a model like the one below (assume as pseudo code )
class Student {
#Id
private String id;
private String firstname;
.....;
#DBRef(lazy=true)
private College college
// getters and setters
}
class College {
#Id
private String id;
private String name;
// other attributes.
// getters and setters
}
I am using #DBRef(lazy=true) so that I do not load the college associated with the student. For example: if I have a repository method for Student called findByFirstname(String firstname), I can load the student without the college.
However, at times I would also want to load the student with college. Is it possible to write a repository method with a custom query using the #Query annotation (org.springframework.data.mongodb.core.query.Query) where I can load the student (all fields) and also the associated college instance ?
#Query( what should go here ?)
Student findStudentWithCollege(String firstname)
If no, then what would be a suggested way to load lazy documents on demand ?
As per the documentation
"DBRefs can also be resolved lazily. In this case the actual Object or Collection of references is resolved on first access of the property. Use the lazy attribute of #DBRef to specify this. Required properties that are also defined as lazy loading DBRef and used as constructor arguments are also decorated with the lazy loading proxy making sure to put as little pressure on the database and network as possible." I guess this may not be suitable for cases where one would want to load a student whose last name is "Smith" along with the college instance for each of the students retrieved.
Consider this mock scenario where I have the following class:
public class Person {
public Guid Id {get;set;}
public string Name {get;set;}
public Address Address {get;set;}
}
I currently have a ReliableDictionary(Guid,Person). I'd like to change my Person model by splitting out the Address, to the following:
public class Person {
public Guid Id {get;set;}
public string Name {get;set;}
}
public class Address {
public Guid Id {get;set;}
public string Street {get;set;}
...
}
I would then have two ReliableDictionaries, one for persons and one for addresses.
What is the proper way to split these entities and migrate the data during an upgrade? I feel like there used to be documentation on this, but I can no longer find it.
Thanks!
An important requirement is that your model needs to be backward compatible. A stored model should be able to load, no matter the changes to your model.
Converting all stored models requires you to loop through the stored models, make changes and store them again. You need to write specific code for this. This could be included in the microservice, or you could create a temporary microservice which calls the microservice which holds the data. After the conversion is done you can remove the code or the microservice.
You could also do this 'on the fly'. Whenever a model is loaded during production you check the version number (you need to specify a version field on your model). If the version is below a certain value, convert it.
I have a Person table that I want to be mapped to multiple foreign keys in a Usage table. Something like this:
public class Usage{
int Id;
int OwnerId;
int CreatedBy;
public virtual Person Owner;
public virtual Person Creator;
}
public class Person{
int Id;
string Name;
}
Now I would like to use Fluent API so I can reference the properties Owner and Creator within an instance of the Usage table. Everything I read says you have to create relationships between both classes (e.g. also map a virtual collection back to the Usage table in the Person table) but I don't want to do that. I don't need a two way relationship. I just want to say that OwnerId and CreatedBy maps to the Person table and load it in memory.
modelBuilder.Entity<Usage>()
.WithOptional(x=>x.Owner).ForeignKey(x=>x.OwnerId)
.WithRequired(x=>x.Creator).ForeignKey(x=>x.CreatedBy)
Is this possible to do? I have a ton of relationships to the Person table and I don't want clutter it up with a bunch of virtual collections that I'll never use.
Thanks!
I'm still trying to get my hands around mongodb and how best Entities can be mapped. if you take for example: the entity user and the entity addresses. there could be one-to-many when someone is coming from jpa background. Here in mongo i don't want to use dbref. So addresses are in a Set collection in user.
Supposing i was using spring-data-mongo:
Question 1 : should both User and Address have the #Document annotation?Or just User?
Question 2 : what is the best way to query for addresses of a user. It is possible at first place? Because right now I query to get the User by username or Id and then get the addresses of the user.Can I query directly for sub-document? if yes how is it done using spring-data-mongo Criteria Query:
#Document
public class User{
#Id
private Long ID;
private String username;
private Set<Address> addresses = new HashSet<Address>();
...
}
#Document
public class Address {
#Id
private Long ID;
private String city;
private String line1;
...
}
Question 1: No, #Document is not strictly necessary at all. We just leverage this on application startup if you activate classpath-scanning for document classes. If you don't the persistence metadata scanning will be done on the first persistence operation. We traverse properties of domain objects then, so Address will be discovered.
Question 2: You'll have to read the User objects entirely as MongoDB currently does not allow returning sub-documents. So you'll have to query for the entire Userdocument but can restrict the fields being returned to the addresses field using a fieldSpec on the Query object or the repository abstraction's #Query annotation (see ref docs).
I’m putting together a code first model that has a lot of reference data. This model is based around applications, servers, and build deployments. Thus, there are a lot of many to many relationships. The pain that I’m feeling is that new records are being placed in the entity tables which I’m attempting to use as reference data. For example, we have a list of servers. I only want to see a server ONCE in the table. For all the entities referring to that server, I want them to use that row. The same can be said of my ServerRoles and Applications tables. These tables contain static data that I’m seeding and should rarely change.
I know I could solve this with look-ups and hand wiring, but I would think EF would comprehend this scenario.
Using Entity Framework code-first you can create an immutable object with protected parameter less constructor and private set properties.
It works for sure with EF 5 Beta.
[Update]
Tested also with EF 4.3.1, it works.
public class Nation
{
protected Nation() {}
public Nation(Guid id, string name)
{
Id = id;
Name = name;
}
public Guid Id { get; private set; }
public string Name { get; private set; }
}