I'm confused with designing a client software with database integration to what should be a member variable of the class or just a query to the database. Let me be specific with a trivial example:
If I have, lets say, a Student class, which has a list of "friends" that are Student objects. Should my software design have an ArrayList<Student> as a member variable of the Student class or should the Database deal with the relationship itself and the Student class doesn't account for those "friends"? How should a proper UML class-diagram be in this case?
This question is broader than you may think, as there are many ways to deal with it. Here some first ideas:
Let's start with a quick class diagram. The friendship between students is a many-to-many association.
In a database, a many-to-many association is usually implemented using an association table. So you'd have two tables: STUDENTS and FRIENDSHIPS with pairs of ids of befriended students:
To load a Student object from the database, you'd read the data in a STUDENTS row and use it to initialize your object. For the friendship, you'd have to read the relevant FRIENDSHIPS rows.
But how to use these tables in the application?
A first possibility would be to load each Student friend and insert it in the ArrayList<Student>. But each loaded student is like the first student and could have oneself friends that you'd have to load as well! You'd end up loading a lots of students, if not all, just for getting the single one you're interested in.
A second possibility would be use an ArrayList<StudentId> instead of an ArrayList<Student> and populate it. You'd then load the friends just in time, only when needed. But this would require some more important changes in your application.
A third possibility is not to expose an ArrayList. Not leaking the internals is always a good idea. Instead use a getter. So you'd load the friends only if student.getFriends() is called. This is a convenient approach, as you'd have a collection of friends at your disposal, but avoid being caught in a recursive loading of friends of friends.
In all the cases, you may be interested in using a repository object to get individual or collections of students, and encapsulate the database handling.
Advice: as said, there are many more options, the repository is one approach but there are also active records, table gateways and other approaches. To get a full overview, you may be interested in Martin Fowler's book Patterns of Enterprise Application Architecture.
You need a one-to-many relationship between Student and friends in both the relational database and the object model.
Related
I'm currently working on improving some old uni assignments moving them from serializable files to any other form of storage, mainly SQL Databases.
I understand the concept of relational database design and the similarities with OOP Classes, however, I'm not entirely sure how to approach this issue from an OOP design perspective.
Right now I have a Hotel class with a List of Rooms as property, each Room has a list of Guests as property (full code here)
Back when using files I could mark these classes with the Serializable interface and store the parent object in a single file. But when using relational DB, I store each list as a single table and use separate queries to obtain the corresponding results. Same goes for the add() operation: with databases, I can do something like Guest.add() and add all the required fields directly to the database, whereas with my current design I need to call Room.getGuestList().add() (or a similar approach).
I totally understand that neither of both approaches is ideal, as both classes should be only worried about storing the data and not about the implementation of an add method, but even if I separate this in a single class, shall I still define a List property within each class?
I'm pretty sure I'm missing a design pattern here, but I cannot find the one that would solve this problem or maybe it's just that I've been taught wrong.
Thanks for your answers
Edit: I've decided thanks to the answers provided to transform my implementation following the DAO pattern as explained in this question and the Oracle documentation.
Normally you would have 3 tables: hotels, rooms, guests.
Rooms would have relation to hotel (hotel id) and guest would have relation to room(room id). That's it.
Those relations can be easily reflected in OOP using some sort of ORM. JPA with Hibernate is an excellent example. Check that out. You will be able to get hotel, its rooms and all guests of hotel just like you described without using a single SQL query in your code.
I am developing a Spring application that use Spring Data JPA to access to the data layer.
So basically I have n entity classes and n related repository classes to access to the data of the database table associated to the entity classes, something like this:
#Repository
#Transactional(propagation = Propagation.MANDATORY)
public interface EntityType1DAO extends JpaRepository<EntityType1, Long> {
//#Query("FROM Room WHERE accomodation = :id")
List<EntityType1> findByEntityType1(EntityType1 entityType1);
}
#Repository
#Transactional(propagation = Propagation.MANDATORY)
public interface EntityType2DAO extends JpaRepository<EntityType2, Long> {
List<EntityType2> findByEntityType2(EntityType2 entityType2);
}
...........................................................................
...........................................................................
...........................................................................
#Repository
#Transactional(propagation = Propagation.MANDATORY)
public interface EntityTypeNDAO extends JpaRepository<EntityTypeN, Long> {
List<EntityTypeN> findByEntityTypeN(EntityTypeN entityTypeN);
}
So basically in this way I have n domain classes accessed by **n repository classes.
I can divide these n domain classes into subsets belonging to a common concept.
For example I can have entity classes like: Room, RoomTipology RoomRate and RoomPicture that all belong to the Room concept.
So I will have the following services classes: RoomDAO, RoomTipologyDAO, RoomRateDAO and RoomPictureDAO.
It works fine but I want adopt a more DOMAIN-DRIVEN DESIGN architecture.
So I have found this interesting article about how to obtain a DOMAIN-DRIVEN DESIGN in Spring application: http://static.olivergierke.de/lectures/ddd-and-spring/
Reading the previous article it says that:
Repository - Spring component, usually a Spring Data repository
interface. Can depend on entities and value objects, are centered
around entities that are aggregate roots.
What exactly means? It means that I can create an aggregate roots class (for example RoomAggregation that aggregate together my Room, RoomTipology RoomRate and RoomPicture entity classes) using the #Embedded annotation.
Or what?
What could be a good architectural solution to obtain a DOMAIN-DRIVEN DESIGN in my application using Spring Data JPA?
You don't create a new class as the Aggregate. Instead you pick one of the exiting ones. Typically it presents itself, and in your example it might be the Room
So you would have a repository for rooms (RoomRepository or Rooms maybe). You use it to save and load rooms, including finding rooms by the various criteria you need.
In order to access (and manipulate) for example a RoomPicture you load the Room navigate to the RoomPicture manipulate it and save your JPA session, which essentially means you are modifying the Room.
If you choose simple navigation between entities (#OneToMany and the gang) or #Embedded ist not affected by your choice of Aggregates, except, that you don't have direct references from on Aggregate to another. So if you also have Booking as an AggregateRoot, that Booking would contai a roomId and you'd use the Room repository to look the Room up.
First of all, forget about Spring Data JPA or any other persistence mechanism. Domain Driven Design is about modelling the domain in analysis and your particular case is about modeling some kind of hotels sub-domain and do not worry about persistence at all. That is another completely different concern not related to hotels but to persistence (another domain or bounded context).
You must think in terms of use cases instead of concepts so we can identify behavior and this way detect invariants that allow us to think about establishing boundaries around what must remain consistent all the time.
Remember to model small aggregates as suggested by Vaughn so your idea of having a big aggregate does not sound good. The hotel manager might instantiate a Room to actually represent a Room and give it a number and some other stuff. Now what about the price and the pictures? Let's take the example of the price and let me ask you, does a Room actually know what its price is? Isn't the room price dynamic and totally affected by a lot of other variables such as dates? Then why to fix a rate inside the Room aggregate? We said a room is not responsable in the real world for such responsibility and the price is affected by several conditions that occur outside the boundary of a Room. So the Rate is totally accidental to a Room, not essential if we talk in philosophy terminology.
The other Aggregate is PriceList and it's Aggregate Root having the same name. So you can ask the price list, the price for an Room (standard, deluxe, ...) in a specific date and it will know the price :)
Depending on how you model all these stuff this might belong to the Pricing Bounded Context exposed as a Microservice, but don't worry
about it. The PriceList is another aggregate completely isolated from the Room and refering the rooms by its conceptual identity that is the Room Number.
The same applies for RoomPicture. In this particular case think that the department/area/employees dealing with the album picture might not be the Manager but someone else with a different role and creating a room album with its own lifecycle.
As conclusiong you would end up having these aggregates:
Room
PriceList
Album
And remember the all these have disconnected associations referring room numbers (not Rooms) and each having its own boundaries around invariants.
In a huge app you might have each of these living in its own bounded context.
Remember Room does not enforce any invariant neither over its album of picture nor its price list.
Hope it helps,
Sebastian.
As #Sebastian has elaborated it very well, when you are DDDing your application, persistance should be the last thing to worry about ever.
You do not couple your entities with the database or else you will end up with a very database driven application messed up with ddd and it will not be presentable in terms of clean code and aesthetic sense.
There is a good presentation on youtube named Domain Driven Design for Database Driven Mind please check it out.
Secondly most of your DAOs should be refactored to Value Objects and you dump al your business logic into Value Objects and Entities and in the end when you need to worry about storing the stuff, just go with a data mapper layer.
Speaking out of experience, value objects done right will offload your 90% weight of the proper app design.
I am going to use ElasticSearch for as the search repository in my application.
I have a few questions regarding what is best practice when it comes to organizing
objects in the search index when the objects have associations/relations to each other.
From what I know search indexes is a flat structure and doesn't work with the concept of
relations in the same way as a database.
Let say you have these domain objects:
Person:
- Has a one-to-many relationship with Car
Car:
- Is owned by one Person, many-to-one with Person
Department:
- Each Department have many People and each Person may belong to many Department, many-to-many
What would be the best way to store this in the search index? What are the options? For instance I want to find all the people belonging to a certain deparment, or all people where the car has more than 300 bhp.
I am using the Java client API if it matters.
Elastic search (or Lucene) isn't a relational database, so you would need to flatten your relationship model.
Try to model a view that gets this structure -
Car|Person|Department
This will give you all attributes required to lookup a car. This can be imported into a document for Car.
Similarly
Person|Department
will give you all information for a person. This will help you lookup a Person
Department can be a third document.
You can have multiple documents for each entity. But the relationship needs to be translated as a property of the entity.
I am learning hibernate an I came across Hibernate Mapping Component.
Why should we use it if we can have the same pojo class for student and address?
You can. But that doesn't mean you want.
Reason one: you want to model them differently
In objects you want to model something the best possible way. That means one thing are Students and other Addresses. In a future you could have more Address per student, or none, so migration to that model will be easier if you have two differents objects.
Think of it as high cohesion and low coupling (good design patterns). Each class has its meaning, its responsability, its limited range of action. The more isolated classes are, the more punctual changes will be. The more modular your code will be too.
By contrast, in tables you make concessions in order to gain performance and more direct queries. That means you can denormalize your model (like joining students and addresses).
Reason two: legacy models
By example. If you have a legacy single table and want to use two objects, you need this mapping. Or... if your application is already made, based on two objects, but your database is reengineered and you decide one table is better.
One more point is that Address (which is treated as component here) cannot have its own primary key, it uses the primary key of the enclosing Student entity.
I'm looking for feedback on the Data Access Object design pattern and using it when you have to access data across multiple tables. It seems like that pattern, which has a DAO for each table along with a Data Transfer Object (DTO) that represents a single row, isn't too useful for when dealing with data from multiple tables. I was thinking about creating a composite DAO and corresponding DTO that would return the result of, let's say performing a join on two tables. This way I can use SQL to grab all the data instead of first grabbing data from one using one DAO and than the second table using the second DAO, and than composing them together in Java.
Is there a better solution? And no, I'm not able to move to Hibernate or another ORM tool at the moment. Just straight JDBC for this project.
I would agree with your approach. My DAOs tend to be aligned more at the object level, rather than from a DB Table perspective. I may manage more than one object through a DAO, but they will very likely be closely related. There is no reason not to have SQL accessing two tables living in one DAO.
And for the record, I have banished the acronym DTO from my vocabulary and code.
Ideally, how you store your data in a database, and then how you access them, should be derived from the nature of the relationship among the domain entities in your domain model. That is, Relational Model should follow from Domain Model. For example, if you have two entities, say, User and Address.
Scenario #1: Address are never accessed independently, they are always an attribute of User.
In this case, Address is a Value Object and User is an Entity, and there are guides on how to store this relationship. One way is to store Address attributes of Address alongside of attributes of User, in a single table. In this case, UserDao will handle both objects.
Scenario #2: Address can be associated to a User, but also can be separate on its own, an entity.
In this case, an approach different from the first one is needed. You may have a separate DAO and table for the Address type.
My point is, that more often this important idea is ignored that Domain Model should be the core of the application, driving other layers.
For instance, if your domain model is properly define and you are well aware of the type of entities you have and the relationship among them, then your persistence (relational tables and their relationships, your DAOs, etc) will evolve as a very logical consequence of what you have in the domain model.
In other words, if you spend some time studying your model, you will be able to trace your problem in determining how to organize your DAOs to a place in the domain model. If you can clearly define the type of the objects and the nature of relationship among them in the domain model, it will, help you resolve your problem in DAL layer.