I'm creating a very simple application in Java that will be storing questions in an embedded Derby database. I've decided to use the DAO pattern for accessing the data in the database. I cannot make use of an ORM for this project.
A question will have data that I would normally model using a many to one relationship in a relational database. An example of this data would be:
A question will have one category. One category will have multiple questions.
A question will have a score of 1000, 2000 or 3000. A score will have many questions.
With the above in mind, I would create three tables (brackets indicate columns):
Question (id, question, scoreId, categoryId)
Score (id, score)
Category (id, category)
My first question is:
Would modelling my data across three tables like I suggest above be bad practice/the wrong way to go about this? Is there any benefit in storing score and category in separate tables? Or would it be better to combine them into the Question table? A many to one relationship that links to a table with a single column (with the exception of id) seems redundant to me, as instead of storing an id referencing the Score/Category table, we can simply store the value of the category/score (since the category/score table does not store any additional information).
My second question is:
If modelling my data across separate tables is the correct approach, then how would I access the data using the DAO pattern? My confusion comes from the following:
I would create a DAO to populate a Question model object that would look a little something like this:
public class Question {
String question;
String category;
Integer score;
}
I would create a concrete implementation of the DAO interface like this:
public class QuestionAccessObject implements QuestionDao {
private static final String TABLE_1 = "QUESTION";
private static final String TABLE_2 = "SCORE";
private static final String TABLE_3 = "CATEGORY";
#Override
public List<Question> getAllQuestions() {
List<Question> questions = new ArrayList<>();
//Run a query with joins across the three tables and iterate over the result to populate the list
return questions;
}
}
Shouldn't each DAO object only be concerned with a single table in the database? My approach listed above doesn't seem like the most correct way to go about this. Seperate tables would also make inserting data into the database very messy (I don't understand how I could take clean approach using the DAO pattern and multiple tables). Creating a DAO for the Score and Category tables just wouldn't really make sense.. (and if I did this, how would I populate my model?)
Would modelling my data across three tables like I suggest above be bad practice/the wrong way to go about this? Is there any benefit in storing score and category in separate tables....?
It's a matter of discussion. In case of score I rather stick this information with the question. On the other hand, the category would be in the separated table since more of the question would share the same category, so it makes a perfect sense.
Shouldn't each DAO object only be concerned with a single table in the database?
Yes, DAO, an object should be concerned with a single source of data - as you say. I would certainly try to avoid any ComplexDao since those classes tend to get more complex and the number of methods increases over the time.
There exist a service layer to combine those results together and provide an output to the controller using the very same service.
Modeling the data across separate tables is A correct approach (not necessarily the best).
Separating tables helps database normalization: https://en.wikipedia.org/wiki/Database_normalization.
One could argue that the DAO pattern implies that each DAO object is concerned with a single entity . Similar to how ORMs work, an entity could easily reference other entities.
When you query for a question you could also just return the category and score ids inside the question object and force the library user to fetch the score value and category value (lazy fetch) using those id values with their respective DAOs (score and category).
So I believe that what you're doing seems fine
Hope this helps
Related
I have two basic document types:
Patient with fields name and number;
Analysis with fields that
consist of 3 arrays, date of analysis, a bunch of floats and a
patientId, linking it to the Patient, so there's a 1:M relationship
between Patient and Analysis.
I'm using Ektorp as a driver. Right now there are two POJOs, reflecting the documents, and Patient POJO also has a Set<Analysis>, marked by #DocumentReferences annotation (which I don't actually need yet, but might use later to show all analyses for one patient, for example).
However, what I want to do is use pagination to populate TableView with rows, containing info about both Patient AND Analysis, sorted by date of analysis in descending order.
Right now, my only idea is to
Query CouchDB for all Analysis documents sorted by date (using
pagination via PageRequest in Ektorp)
Then for each analysis query db for patients with patientId
Make a separate class representing a row in table with fields for both patient and analysis, then create an object of that class using
retrieved Analysis and Patient objects.
In code it would look somewhat like this:
PageRequest pageRequest = PageRequest.firstPage(5);
ViewQuery query = new ViewQuery()
.designDocId("_design/analysis")
.viewName("by_date")
.descending(true)
.includeDocs(true);
Page<Analysis> result = db.queryForPage(query, pageRequest, Analysis.class);
for(Analysis analysis : result) {
Patient patient = db.find(Patient.class, analysis.getPatientId());
Row row = new Row(patient, analysis);
//TODO: ...Populate TableView...
}
This all sounds very cumbersome. Is there a better way to do this? Can I deserialize data I need in one go (or at least in one query)?
I know there's a way to use {_id: doc.patientId} as a value in emit() function to return Patient for each Analysis when querying with parameter include_docs=true, but I'm not sure how to use that to my advantage.
I could just embed Patient in Analysis, but then I would have to change every Analysis document if there's a change in Patient, so that's not a good solution.
I've read these two paragraphs of documentation several times over, but I can't for the life of me figure out how to implement them with Ektorp.
Any help would be appreciated.
Suppose I am using SQL and I have two tables. One is Company, the other is Employee. Naturally, the employee table has a foreign key referencing the company he or she works for.
When I am using this data set in my code, I'd like to know what company each employee works for. The best solution I've thought of it to add an instance variable to my Employee class called Company (of type Company). This variable may be lazy-loaded, or populated manually.
The problem is that many employees work for the same company, and so each employee would end up storing a completely identical copy of the Company object, unnecessarily. This could be a big issue if something about the Company needs to be updated. Also, the Company object would naturally store a list of its employees, therefore I could also run into the problem of having an infinite circular reference.
What should I be doing differently? It seems object oriented design doesn't work very well with relational data.
This is more of a design/principles sort of question, I do not have any specific code, I am just looking for a step in the right direction!
Let me know if you have any questions.
Do not try design your business objects to mirror database schema.
Design objects to serve your business requirements.
For example in case when you need to display list of employees without company information, you can create function which retrieve only required information from database to the object
public class EmployeeBasicInfo
{
public int Id;
public string Name;
}
For next requirements you need a list of employees with full information - then you will have function which retrieve full data from database
public class Employee
{
public int Id;
public string Name;
public int Age;
public CompanyBasicInfo Company;
}
Where Company class will not have collection of employees, but will have only information required for Employee class.
public class CompanyBasicInfo
{
public int Id;
public string Name;
}
Of course in last case you end up with bunch of different Company objects which will have same data. But it should be Ok.
If you afraid that having same copy of data in different object will cause a performance problem, it will not until you will load millions of employees - which should be good sign of something gone wrong in your application design.
Of course in situation where you actually need to load millions of employees - then you can use approach that class which loads employees - will first load all companies in the Map<int, Company>, and then when loading employees you will refer same Company instance for employees.
Am I really the only person who is running into this issue? There must be some way to do this without relying on lazy-loading every property.
This problem has been solved many times before already. Avoid re-inventing the wheel by using any of the widely available ORM frameworks.
In a database table, the primary key identifies a record; in a running application, the reference tracks an object; and, at an even lower abstraction, a memory address points to the bytes that represent that object.
When you initialise an object and assign it to a variable, the variable is sufficient to track the object in memory so that you can subsequently access it. However, in the database layer, a primary key is needed to locate the record in a database table. Therefore, to bridge the gap between the relational model and the object model, the artificial identifier property is required in your object.
At my company we work with models based on "Active Record Pattern", the model methods are always related to operations of a single record from the database, for example:
Class User {
int id;
string Name;
public boolean Find (id); // SQL / ORM to return the object based on the user's Id;
public boolean Save (); // SQL / ORM to save / update a user
public boolean Delete (); // SQL / ORM to delete a user.
}
// Create the user "John"
Set objUser = new User ();
objUser.Name = "John";
objUser.Save ();
My question is that in relation to the database entity "User", we have methods that are to table level and not record, such as a method "getAllActiveUsers", which returns me a query object of all active users.
This type of situation ends up in own ActiveRecord model, which in my opinion does not make sense .. Could you help me to understand what would be the most advisable / elegant to treat this type of situation?
I read something about Gateway and Repository Patterns that may be useful for this, but was wondering if anyone has this same trouble and how did you solve ..
Thank you!!
I'm not a big fan of the Active Record Pattern but I think a consistent way of using it would be to add the getAllActiveUsers to the User class:
User.getAllActiveUsers();
On the other hand I would reccommend to use the Repository Pattern in the following cases:
You want to take advantage of Unit Testing.
You access the data source from many locations and you want to abract complexity.
You want a centralized place to handle caching.
You want a clear separation of concerns.
You want to apply a domain model so to simplify complex business logic.
Best Way to Design database for AutoComplete Functionality.
I have following usecase(using technologies JAVA,SPRING,HIBERNATE,Mysql):
I have Professional Details Which is Associated with Skills(Many to Many Relationship).
public class ProfessionalDetailsDTO {
private Integer professionalId;
//many to many
private List<SkillsDTO> profileSkills;
setter and getter ...
}
public class SkillsDTO {
private String skillName;
private Integer skillRating;
private Integer skillId;
setter and getter
}
Now From UI When I type Type Skills I should get the Valid Skills Suggestion (like JAVA,Hibernate).people might Save Dummy Skills or abrupt value
(e.g XYZ )in Skill Table ,So I don't Want to Show This as suggestion in autoComplete.
I Can Think of Following Approaches Right Now:-
Approach 1 : Having Four Tables as mentioned below
1.ProfessionalDetails
column:professionalId
2.Skills
column:SkillId,skillName,skillRating
3.Professional_Skills
column:skillId,professionalId
4. PreDefinedSkill
column:id,SkillName
Is it BestPractice to have one more table for preDefined Skills Which will be used for AutoSuggestion and The SkillName Fetched from the
predefined Table will be stored in the skills table?
Cons:SkillName Will be Duplicates in the Skills Tables.
Approach 2 : In this Approach SkillRating is Moved to professional_Skills Table and Skillname is unique in skillTable
Here I have to Map SkillDTO to Tables.I have to use annotaion Such as #secondaryTable.
1.ProfessionalDetails
column:professionalId
2.Skills
column:SkillId,skillName
3.Professional_Skills
column:skillId,professionalId,,skillRating
Approach 3 .Same as Approach 2 but instead of using hibernate annotation use query's to insert into professional_Skills table.
Please Suggest me Some Best Industry Practices To Implement the Above usecase
Thanks in Advance.
The Best Solution to Implement the Above use case(i.e Many to many with Additional Columns) is described in the Below Link:
http://en.wikibooks.org/wiki/Java_Persistence/ManyToMany
Posting this as this might Help others.
I have previously used Hibernate and now I am trying to understand JDBC. I have done loads of research on Spring JDBC but still I could not understand how to create relationships between objects.
Assume I have a Product:
public class Product {
private Long id;
private String nam;
private Customer customer;
//constructor, getters and setters.
}
and a Customer:
public class Customer {
private Long id;
private String name;
private List<Product> products = new ArrayList<Product>();
//constructor, getters and setters
}
The relationship between Customer and Product is #OneToMany.
How to correctly save the product and customer objects in the db using SpringJDBC?
Thank you
It make a lot of sense in quite a few cases to not use a full blown ORM but rely on lower level of abstraction, like Spring JDBCTemplate and RowMapper. iBatis comes to mind as well. And that make sense even in large enterprise solutions.
If you leave the full blown ORM world, you will have to do additional work yourself. For example, you can write an SQL query with a join, returning all customer fields and all products of that customer, and iterate through it to map all that to Java object. In quite a few cases, the code can be as clean as what you would have with an ORM.
Writing all that data is more messy, especially if you need to optimize for stuff that has not been dirtied.
Best use case I can think of is batch processing, where control over data access becomes more important and higher level of abstraction do not necessarily make you more productive.
If you are willing to consider something other than spring or hibernate, sormula can do what you describe. See the one to many example. If you name the foreign key on the many side the same as the primary key on the one side, then you don't need any annotations.
To store a reference to one-side object (Customer) in the many-side objects (Products), you can use the OneToManyCascade#foreignKeyReferenceField. For examples, search the tests in the project for "foreignKeyReferenceField".
If I understand your question correctly, if think if you are not using ORM you would have to do this manually.
In your DAO class for Customer it would first have to persist all the products.
An alternative might be to create a Stored Procedure on the database and have that sort out the correct persistence.
This can be handled very nicely by Spring JDBC, the downside is you know have to manage Java and Stored Procedures.
In your case it might still be two Stored Procedures.
There is also the possibility that QueryDSL and Jooq, thought I haven't had a chance to have a good look at them.
I personally like the Stored Procedure solution, for me the additional over head is worth it, I know others disagree, but I just don't like/buy the ORM deal.