I am building an application which allows restaurant guests to order food and send to server.
What i have considered is to
1) create a class Order.java class
public class Order
{
private Intger tableId;
private Integer restaurantId;
private Integer foodId;
private Integer foodQuantity;
getter and setters
}
2) This class object will be populated with guests order and an ArrayList of objects of the class will be sent to server as Gson String.
Now if an order consist of some 7 items, Then the arraylist will have 7 objects, but tableId and restaurantId will be same 7 times.
can you suggest a better design where in I can associate restaurantId and tableId with the entire arraylist.
Thanks.
There is no right solution, it would depend on your needs, one possible solution would be something like:
public class Order {
private int tableId;
private int restaurant;
private List<OrderItem> items;
// setters and getters
}
public class OrderItem {
private int itemId; // foodId
private int quatity; // foodQuantity
// setters and getters
}
But if you were in a situation that the information comes not normalized, like you suggested (in which tableId is repeated for every single food ordered), I would consider to implement a normalization process that will return a structure with the classes I draft above. But if you are implementing it, please consider to make it as normalized as possible.
Related
I'm struggling to write this, so I may have to give an example to help explain the problem I'm experiencing.
Say we have nodes of three types (these nodes may have more relationships of their own, e.g. Product Family, has product manager):
Product
Product Family
Battery
With these relationships
A product can be be in 0 or more families
A product can have 0 or more batteries.
When using spring-data-neo4j and saving a new Product, I wish to include these relatiopnships, such as the batteries they require and the product family they belong to. However if I only supply say an ID rather then a fully populated object, it overwrites this object along with properties and relations accordingly.
This isn't great as it means that I have to end up sending a fully populated object, with all it's relations everytime I wish to save something, and some of these relations may go quite deep.
My domain is as follows:
#Node
public class Product {
#Id
#GeneratedValue(generatorClass = SnowflakeGenerator.class)
private Long productId;
private String name;
#Relationship(type = "REQUIRES_BATTERY", direction = OUTGOING)
private List<Battery> batteryList;
#Relationship(type = "IN_FAMILY", direction = OUTGOING)
private List<ProductFamily> productFamilyList;
}
#Node
public class Battery {
#Id
#GeneratedValue(generatorClass = SnowflakeGenerator.class)
private Long batteryId;
private String name;
}
#Node
public class ProductFamily {
#Id
#GeneratedValue(generatorClass = SnowflakeGenerator.class)
private Long familyId;
private String name;
}
This could very well by from coming from a Relational Database mindset and is a 'limitation' of using Neo4J.
TLDR When persisting somethign in Neo4J using spring-data how can I save just a relationship, rather than a whole related Node.
You can make use of projections in Spring Data Neo4j. (https://docs.spring.io/spring-data/neo4j/docs/current/reference/html/#projections)
This gives you the option to put a "mask" on the object tree, you want to persist (and what should stay untouched).
For example in your case:
interface ProductProjection {
// without defining e.g. String getName() here, SDN would not ever touch this property.
List<BatteryProjection> getBatteryList();
List<ProductFamilyProjection> getProductFamilyList();
}
interface BatteryProjection {
String getName();
}
interface ProductFamilyProjection {
String getName();
}
So I'm trying to create a project based in some weather forecast API and the data comes in different objects like:
public class WeatherForecast{
private String local;
private int maxTemp;
private int minTemp;
private int precipitationId;
}
public class Precipitation{
#Id
private int id;
private String descriptionEn;
private String descriptionCh;
...
}
So, I want to store this information and obtain the description of the Precipitation in the language that I desire, without receiving an WeatherForecast with the description of 10+ languages.
I searched a lot about defining relations between the tables but I couldn't find something related to relationships by id's. I found that I could use,
#DbRef
private Precipitation precipitation;
but I couldn't understand how it can interpret the Id without passing in the constructor.
And, finally, I want to understand if it's a good practice to send the two objects
separately to the database and try to workout some functionality to get the object I want, something like this:
public class WeatherForecast{
private String local;
private int maxTemp;
private int minTemp;
private String description;
}
using criteria, queries, or other things without extracting the two tables and searching in Precipitations for the desired description language.
Imagine you have a journal of student evaluations. Each student have some marks of each subject in a journal in some day. Is there a better way to add mark of student by specific date?
I tried to store this data in HashMap<Student, HashMap<Subject, ArrayList<Integer>>> (my previous question) but I think this way is bulky and is not efficient enough.
class School {
private List<Classes> classes;
...
}
/**
* Classes contains data of school classes (students, subjects etc)
*/
class Classes {
private List<Students> students;
private List<Subjects> subjects;
private List<Teachers> teachers;
...
}
/**
* Class Mark is a collection of student marks
* Contains Mark, Subject and Date values
*/
class Mark {
private Date date;
...
}
Any ideas to store this one more efficient with create/read/update/delete actions? I'll be glad to get tips how do I organize these classes.
The simplest solution to your problem is to have Mark class with the following fields:
public class Mark {
private Integer value;
private Date date;
private Student student;
private Subject subject;
//getters & setters
}
This will allow to get all the marks of a concrete student from any Collection<Mark> marks using filtering methods (google guave libs provide such an API, with Java 8 it's even easier to do as it is now in java.util.stream).
Nevertheless, if you are willing to have your data structure with marks already sorted on a concrete student, I would suggest to implement a backward relation between Student and Mark:
public class Student {
private Collection<Mark> marks;
//getters & setters
}
Now you operate on Collection<Student> students and may get the marks on a concrete student from the collection.
Finally, if you would like to operate on a data structure with marks already sorted by Student and Subject you may use an additional abstraction:
public class StudentPerformance {
private Student student;
private Map<Subject, List<Mark>> marks; //actually it can be implemented
//with a class as well but let's leave it as it is
//for the sake of simplicity of the example
//setters & getters
}
And then store it as a collection: Collection<StudentPerformance> performances
The pros for such a solution:
Less verbosity in your client code
It is more descriptive
You use one of the main features of Java - strong typing. It means that it is guaranteed in compile time that your client code would not accept anything which is not of type StudentPerformance. And it really helps to avoid bugs in large projects.
Finally, the concrete solution is always dependent on the needs of your application. There is no silver bullet.
I don't think that use a complex key in a HashMap is a good idea.
I would do something like this:
class Evaluation {
private Subject Subject;
private Date date;
private List<Mark> marks;
//getters & setters
}
class Mark {
Student student;
int score;
//getters & setters
}
So now in Classes you will have:
class Classes {
private List<Students> students;
private List<Subjects> subjects;
private List<Teachers> teachers;
private List<Evaluation> evaluations;
...
}
I've created an entity with a pojo (ProductVariations) using the label #Serialize to be persisted in GAE through objectify:
#Entity
public class Product extends DatastoreObject{
//Reference without the colors and size information
#Index private String ref;
private double price;
private String details;
private String description;
#Serialize private ProductVariations pVariations;
private List<String> tags = new ArrayList<String>();
//Getters & Setters
}
The problem is that I don't see how to access my pojo with requestfactory because ProductVariations is not a domain type.
In any other case I would use an embeded object but in this particular case I have a nested collection inside ProductVariations witch is a collection in itself (ProductVariations extends ArrayList).
Any suggestions in how to achieve this?
Thank you.
Not sure I understand your question, but you need to implement Serializable in Product if you want to send it over RPC.
Beyond that, are you having problems storing ProductVariations? It's an interesting concept. If it isn't working:
Can you keep ProductVariations in its own #Entity?
Then keep a Key in Product class (or a Long that can you can create a Key from).
For convenience you can also leave ProductVariations in Product but mark it with #Transient and then populate it from the Key/Long in the factory that does your ofy.get().
Is it possible to store something like the following using only one table? Right now, what hibernate will do is create two tables, one for Families and one for people. I would like for the familymembers object to be serialized into the column in the database.
#Entity(name = "family")
class Family{
private final List<Person> familyMembers;
}
class Person{
String firstName, lastName;
int age;
}
This is an horrible design and I'm really not recommending it (you should just create another table) but it is possible.
First, you'll need to use a byte[] attribute to hold a serialized version of the list of persons that will be stored in a BLOB in the database. So annotate it's getter with #Lob (I would make the getter and setter private to not expose them). Then, expose "fake" getter and setter to return or set a List<Person> from the byte[]. I'm using SerializationUtils from Commons Lang in the sample below (provide you own helper class if you don't want to import this library) to serialize/deserialize on the fly to/from the byte[]. Don't forget to mark the "fake" getter with #Transcient or Hibernate will try to create a field (and fail because it won't be able to determine the type for a List).
#Entity(name = "family")
class Family implements Serializable {
// ...
private byte[] familyMembersAsByteArray;
public Family() {}
#Lob
#Column(name = "members", length = Integer.MAX_VALUE - 1)
private byte[] getFamilyMembersAsByteArray() { // not exposed
return familyMembersAsByteArray;
}
private void setFamilyMembersAsByteArray((byte[] familyMembersAsByteArray() { // not exposed
this.familyMembersAsByteArray = familyMembersAsByteArray;
}
#Transient
public List<Person> getFamilyMembers() {
return (List<Person>) SerializationUtils.deserialize(familyMembersAsByteArray);
}
public void setParticipants(List familyMembers) {
this.familyMembersAsByteArray = SerializationUtils.serialize((Serializable) familyMembers);
}
}
Don't forget to make the Person class Serializable and to add a real serialVersionUID (I'm just showing a default here):
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
// ...
private String firstName, lastName;
private int age;
}
But, let me insist, this is an horrible design and it will be very fragile (changing Person might require to "migrate" the content of the BLOB to avoid deserialization issues and this will become painful. You should really reconsider this idea and use another table for the Person instead (or I don't get why you use a database).
#Type(type = "serializable")
private List<Person> familyMembers;
if you can't use hibernate annotations try this:
#Lob
private Serializable familyMembers;
public List<Person> getFamilyMembers(){
return (List) familyMembers;
}
public void setFamilyMembers(List<Person> family){
familyMembers = family;
}
Annotate the property with #Column and define the type to be ArrayList, not just List. And make Person implement Serializable.
But you should do this only if your motives are very clear, because this is the correct solution in some very rare cases. As Pascal noted, if you ever have to change Person you'll have headaches.
You can create pseudoproperty (getter and setter) which accepts/returns the serialized form, and annotate the familyMembers with #Transient. This would also need to annotate the getters, not fields, for all other properties.