Say I have a person object with a field that is profession, which is simply a list of strings. What is the canonical way, using Spring and hibernate, to restrict this list to only a subset of professions that are defined by either user or the admin? Ie, the list of global, predefined professions at runtime is {Accountant, Developer}, and the user adds 'Plumber' to the list. Now if a new person is created, I'd like to restrict the possible professions that person can have to the 3 that are in the list.
Originally, I implemented an Enum, but this seems like a poor design, as it's generated at compile time, and can't be added to at run time (I think?). Would the proper way be to define a one column table with profession, and at each request to make a person, populate a singleton with one member, which is a list of the professions? Then the domain object person would only source the profession from the singleton (presumably in the service layer?).
You can create a new Entity Profession which is related to Person with a one-to-many relationship. This way a profession is always only what is persisted by Hibernate. The profession entity does not need much. Just an id and name for now. Later you might add more attributes as you need.
Related
I am working on a little website. The database was created and we need to create objects from sql now.
Usually, in "Many to many" relation, I use a list to represent this relation. (List of ingredient in recipe, and if I need, a list of recipe in ingredient).
But I don't know what is the best way when the junction table contain field.
For example with theses tables:
###### #################### ##########
RECIPE INGREDIENT_IN_RECIPE INGREDIENT
id id_ingredient id
name id_recipe name
quantity
other
Is there a best way to create object from this sql?
I don't know if:
I need to create an third object "IngredientInRecipe". And list it on recipe/ingredient?
Maybe create fields quantity/other in ingredient and use it only when I want to handle ingredient as "ingredientinrecipe"?
Or create a Subclass of Ingredient with quantity/other?
Maybe I'm totally wrong and I just have to create list in recipe and use sql query or array for other things but I'm little bit lost.
This is a simple association class and you would model it like this:
You concrete object model with single tables it pretty fine.
The answer here is based on the question is the INGREDIENT_IN_RECIPE an entity by itself, or is it just a relational table to create the many to many in the db.
Currently, INGREDIENT_IN_RECIPE contains additional information, that is really important and further specifies the relation between RECIPE and INGREDIENT, so this qualifies it is a proper entity.
IMHO, the best way here is to create a entity class for the INGREDIENT_IN_RECIPE table and list it on the RECIPE entity class at least. You need to check if the relation from the INGREDIENT entity is really needed and useful.
I am currently working on a product that works with Hibernate (HQL) and another one that works with JPQL. As much as I like the concept of the mapping from a relational structure (database) to an object (Java class), I am not convinced of the performance.
EXAMPLE:
Java:
public class Person{
private String name;
private int age;
private char sex;
private List<Person> children;
//...
}
I want to get attribute age of a certain Person. A person with 10 children (he has been very busy). With Hibernate or JPQL you would retrieve the person as an object.
HQL:
SELECT p
FROM my.package.Person as p
WHERE p.name = 'Hazaart'
Not only will I be retrieving the other attributes of the person that I don't need, it will also retrieve all the children of that person and their attributes. And they might have children as well and so on... This would mean more tables would be accessed on database level than needed.
Conclusion:
I understand the advantages of Object Relational Mapping. However it would seem that in a lot of cases you will not need every attribute of a certain object. Especially in a complex system. It would seem like the advantages do not nearly justify the performance loss. I've always learned performance should be the main concern.
Can anyone please share their opinion? Maybe I am looking at it the wrong way, maybe I am using it the wrong way...
I'm not familiar with JPQL, but if you set up Hiernate correctly, it will not automatically fetch the children. Instead it will return a proxy list, which will fetch the missing data transparently if it is accessed.
This will also work with simple references to other persistent objects. Hibernate will create a proxy object, containing only the ID, and load the actual data only if it is accessed. ("lazy loading")
This of couse has some limitations (like persistent class hierarchies), but overall works pretty good.
BTW, you should use List<Person> to reference the children. I'm not sure that Hibernate can use a proxy List if you specify a specific implementation.
Update:
In the example above, Hibernate will load the attributes name, age and sex, and will create a List<Person> proxy object that initially contains no data.
Once the application accesses calls any method of the List that requires knowledge of the data, like childen.size() or iterates over the list, the proxy will call Hibernate to read the children objects and populate the List. The cildren objects, being instances of Person, will also contain a proxy List<Person> of their children.
There are some optimizations hibernate might perform in the background, like loading the children for other Person objects at the same time that might be in this session, since it is querying the database anyways. But whether this is done, and to what extend, is configurable per attribute.
You can also tell hibernate to never use lazy-loading for certain references or classes, if you are sure you'll need them later, or if you continue to use the persistent oject once the session is closed.
Be aware that lazy loading will of course fail if the session is no longer active. If for example you load a Person oject, don't access the children List, and close the session, a call to children.size() for example will fail.
IIRC the hibernate session class has method to populate all not-yet-loaded references in a persistent oject, if needed.
Best read the hibernate documentation on how to configure all this.
I have an issue in performing Hibernate Mapping. The scenario is as follows:
There is a User class which has username, name, dateofbirth, image and other information pertaining to a user with username as the primary key.
Second class is Product class which has product id and other information related to a product with primary key as product key.
The third class is Order class which has OrderId, OrderDate, Username- should be foriegn key-referring to the User class username and finally a Set of type Product- because one order can have many products.
Now I want the primary key of the Order class as a composite key (OrderId, ProductID) and this productID should be reference from Product Class.
The relationships that I want to create are as follows:
1. One order can belong to only one User
2. One order can have many products
Can someone lead me on how to go about it? Any kind of help will be great.
I think most likely you are thinking similar relationship. Difference in your requirement is you need One to Many mapping from Order/PurchaseOrder to Product/Item and you don't want Shipment.
My suggestion would be:
Create bi-directional one-to-many relationship b/w User and Order. Benefit for bidirectional is you can access User Object from Order Object, if not required, you can keep it unidirectional from User to Order.
Create one-to-many relationship b/w Order and Product.
Instead of composite key in order, keep the primary key as just OrderID. You can still fetch list of products from your order object and order object from user object.
The whole point in making this decision is from which object you derive remaining objects. With ORMs you should know from which object you would derive rest and so my suggestion is based on assumption that you will have User object available as attached entity, so you can get list of orders (defined as set) and from a particular order find out list/set of Products.
In case you have Order object available first, then create a bidirectional with User. So that you can find list/set of Products at one end, and Customer associated at other.
For ORM mappings refer Hibernate Mapping Examples.
Hope this clarifies.
I am completely fresh to both JDO and GAE, and have been struggling to get my data layer to persist any code at all!
The issues I am facing may be very simple, but I just cant seem to find any a way no matter what solution I try.
Firstly the problem: (Slightly simplified, but still contains all the info necessary)
My data model is as such:
User:
(primary key)
String emailID
String firstName
Car:
(primary key)
User user
(primary key)
String registration
String model
This was the initial datamodel. I implemented a CarPK object to get a composite primary key of the User and the registration. However that ran into a variety of issues. (Which i will save for another time/question)
I then changed the design as such:
User: (Unchanged)
Car:
(primary key)
String fauxPK (here fauxPK = user.getEmailID() + SEP + registration)
User user
String registration
String model
This works fine for the user, and it can insert and retrieve user objects. However when i try to insert a Car Object, i get the following error:
"Cannot have a java.lang.String primary key and be a child object"
Found the following helpful link about it:
http://stackoverflow.com/questions/2063467/persist-list-of-objects
Went to the link suggested there, that explains how to create Keys, however they keep talking about "Entity Groups" and "Entity Group Parents". But I cant seem to find any articles or sites that explain what are "Entity Group"s or an "Entity Group Parents"
I could try fiddling around some more to figure out if i can store an object somehow, But I am running sort on patience and also would rather understand and implement than vice versa.
So i would appreciate any docs (even if its huge) that covers all these points, and preferably has some examples that go beyond the very basic data modeling.
And thanks for reading such a long post :)
I'm afraid you won't like the answer. GAE JDO has to be used a very specific way and is fraught with limitations that you have to observe to use it effectively. Read the docs forwards and backwards. For the issue you are seeing now, you probably need to read this section a couple of times:
http://code.google.com/appengine/docs/java/datastore/relationships.html
GAE JDO has owned and unowned relationships. See the documentation above for examples of owned vs unowned. I believe you want Car and User to have an unowned relationship. Note this revelation in the Google App Engine documentation about unowned relationships:
http://code.google.com/appengine/docs/java/datastore/relationships.html#Unowned_Relationships
In addition to owned relationships, the JDO API also provides a facility for managing unowned relationships. The App Engine implementation of JDO does not yet implement this facility, but don't worry, you can still manage these relationships using Key values in place of instances (or Collections of instances) of your model objects.
This essentially means, to use GAE JDO, you should not use a direct reference for an unowned relationship like between the Car and User classes. Rather, you should use indirect references between them, i.e. Car should have a field for the User's key rather than a direct reference to the User itself. Some of the trouble you are having is because GAE JDO cannot deal with how you are modeling this relationship in code.
Asker goes on to say:
Went to the link suggested there, that explains how to create Keys, however they keep talking about "Entity Groups" and "Entity Group Parents". But I cant seem to find any articles or sites that explain what are "Entity Group"s or an "Entity Group Parents"
Entity Group - a graph of objects that were initially persisted together. For example, because Car refers directly to a User, when you persist a given Car instance for the first time, then you would also persist the User instance to which it refers and this Car instance and this User instance would be part of the same entity group. If this User instance was already been persisted, either independently by itself or as part of another Car instance, then this User instance is already in another entity group. "Owned" relationships are supposed to be in the same entity group. Note that GAE JDO transactions can modify only 1 entity group - any more will raise an exception.
Entity Group Parent - a top-level/root ("parent") persisted class. In the above example, when you persist a given Car instance for the first time, you would also persist the User instance it refers to. The Car instance is the entity group parent. An "owned" "child" class like User embeds its parent's (Car's) key within its own (User) key. If you were to pull a Car instance from the database and then attempt to access the User that this Car refers to, then the GAE JDO will use the Car's key to find the corresponding User (because the target User's key has the parent Car's key embedded as part of its own key).
Asker got this error message:
"Cannot have a java.lang.String primary key and be a child object"
Note this statement in the docs:
The child class must have a key field whose type can contain the parent key information: either a Key, or a Key value encoded as a string. See Creating Data: Keys for information on key field types.
This means that "child" classes must use certain types of keys (i.e. keys that are capable of encapsulating their parent's key within the child's key). Long and String are suitable for entity group parents classes, i.e. non-child classes. However, "child" classes must use either Key or Key encoded as String type for their key. The error message indicates that the Car class refers to the User class as if it were an "owned" "child" class, and therefore the User class must use an key type appropriate for a child, but the User class is not using a key type appropriate for a child (non-encoded String).
The fix for the immediate problem at hand is to model Car and User to be an unowned relationship by changing Car from having the direct reference to User to instead having an indirect reference by storing the related User's key. The overall fix will likely include taking a hard look at how to fit your object model into GAE JDO's framework (once you wade through the docs to try to understand it). This will likely include having to manually manage some of the relationships between the classes.
If its any consolation, I'm dealing with the same sort of issues with GAE JDO myself (I even have a Car class too!).
Read http://code.google.com/appengine/docs/java/datastore/relationships.html
I have the DB structure as follows:
table STUDENT (say, id, surname, etc)
table STUDENT_PROPERTIES (say, name_of_the_property:char, value_of_the_property:char, student_id:FK)
table COURSE (id, name, statusofcourse_id)
table STATUSOFSOMETHING (id, name_of_status:char ('active','inactive','suspended' etc))
table STUDENT_COURSE (student_id,course_id,statusofsomething_id)
Let's try to pick up domain objects in my database:
Student and Course are main entities.
Student has a list of courses he attends, also he has a list of properties, that is all for this student.
Next, Course entitity. It may contain a list of students that attend it.
But in fact, the whole structure looks like this: the starting point is Student, with it's PK
we can look a list of his properties,
then we look into the STUDENT_COURSE and extract both FK of the Course entity and also the Status
of the combination, it would look like "Student named bla bla, with all his properties,
attends math and the status of it is "ACTIVE".
now, quotation
1) Each DAO instance is responsible for one primary domain object or entity. If a domain object has an independent lifecycle, it should have its own DAO.
2) The DAO is responsible for creations, reads (by primary key), updates, and deletions -- that is, CRUD -- on the domain object.
Now, first question is
What are entities in my case?
Student, Course, Student_Course, Status = all except for StudentProperties?
Do I have to create a separate DAO for every object?
The entities you will need to create are:
Student
StudentProperties
Course
CourseStatus (not really necessary as you could use an enumerated field in Course instead)
StudentCourse doesn't need to be created, as you can just use a Many-to-Many mapping in Hibernate and it will give you a nice set of courses in your Student object.
Here's a great tutorial on hibernate mapping that does pretty much everything you need:
http://www.vaannila.com/hibernate/hibernate-example/hibernate-mapping-many-to-many-1.html