In one of my projects, I have an application that manages several clients (or customer if you prefer). For each of them, I have a dedicated schema on a database.
However, the application handles only one client at a time, i.e. the user must switch from one client to another in the application (at runtime, no restart of the application) in order to access the data from this new client.
How would you manage the connections, as well as the persistence layer, for this kind of project?
I want to use Hibernate for that. What are the points on which I must be really carefull when dealing with several database / schemas ?
Can Spring be of any help in this case?
If I am not clear enough, let me explain the situation with an example.
Imagine that my application can handle two clients: clientONE and clientTWO.
I already implemented a class that can provide me the database schema, user, password and connection String for a given client.
Each client have a list of debtors, but unfortunately, the DEBTOR table structure is not the same for clientONE and clientTWO.
Even the names of tables / columns are not the same...
So I can create one debtor class per client (I use Hibernate annotations):
#Entity
#Table(name = "T_DEBTOR_ONE")
...
public class ClientOneDebtor {
#Id
#Column(name = "ID_DEBTOR")
private String idDebtor;
...
}
and:
#Entity
#Table(name = "T_DEBTOR_TWO") // Table names are not the same among the different schemas...
...
public class ClientTwoDebtor {
#Id
#Column(name = "DEBTOR_ID") // It's just to show that the same information is stored in a column that has not the same name.
private String idDebtor;
...
}
Ideally, I will try to have a common Debtor class (here is an Abstract class, but I may use an Interface):
public abstract class AbstractDebtor {
public abstract String getIdDebtor();
...
}
#Entity
#Table(name = "T_DEBTOR_ONE")
...
public class ClientOneDebtor extends AbstractDebtor {
#Id
#Column(name = "ID_DEBTOR")
private String idDebtor;
...
}
#Entity
#Table(name = "T_DEBTOR_TWO")
...
public class ClientTwoDebtor extends AbstractDebtor {
#Id
#Column(name = "DEBTOR_ID") // It's just to show that the same information is stored in a column that has not the same name.
private String idDebtor;
...
}
This way, it will be easier for me to manipulate the Debtor objects in my DAO / Service layer, as I will not need to duplicate my DAO and Services for every client.
For example, the method from DAO to get the list of all Debtors will be public List<AbstractDebtor> getAllDebtors() { ... }.
So, how would I change the context when I change the client managed by my application?
In others words, how would I indicate to Hibernate (or Spring?) that I want to use the correct persistence objects (ClientOneDebtor or ClientTwoDebtor) regarding the client that is currently managed by my application?
If you think that I am going in the wrong direction, do not hesitate to share your ideas on how to solve this kind of problem...
Edit regarding the first answers:
The number of different schemas I will need to handle is around 15 - 20. In addition to that, I will only need to map only a little subset of their tables.
I also know that having one schema per client/customer is not the best solution for storing data. However, this architecture exist since 5 years, and we may move to only one schema during the next year (in the best case ;) ).
If only one at a time will every be required, it makes it much simpler. Simply create a SessionFactory per database. Avoid the HibernateUtils static SessionFactory instance approach and you won't have any problems.
A neat way to do this with Spring if you don't have too many databases (hundreds) is to instantiate a separate Spring ApplicationContext for each one that contains the SessionFactoryBean and DataSource configurations specially for that database.
You can use Spring mechanisms like PropertyOverrideConfigurer and a common parent ApplicationContext to factor out all the common stuff so that your many child ApplicationContexts are small and maintainable.
Then when a request comes in, just select the ApplicationContext you want to work with and start pulling beans out of it.
If you want to do it without Spring, you could also create multiple SessionFactory instances and store the "current" one in a static ThreadLocal.
Unfortunately, the Real World often does require multiple databases/schemas, especially when you have a vendor product whose database must be distinct from your corporate databases.
Making an arbitrary number of databases would be a mess, and for that, you really SHOULD consider a better form of data organization. But for a fixed (hopefully small) set of databases, just define them in the persistence configuration with a separate PersistenceUnit for each (which implies a separate EntityManager).
Using your illustrated inheritance scheme, you would assign the appropriate EntityManager to each derived class, assuming that the framework lets you.
Related
I would like to understand what's the benefits to create DTO objects when you already have POJO object (as Entity).
In my project I have both :
DTO classes are used to communicate between Web Service and the application
POJO entity classes (JPA) are used for communication between database and the application
If I look at a DTO object class (let's call it MyObjDTO) and the same class but POJO side (let's call it MyObjPOJO) there is no difference at all except MyObjPOJO as annotation due to the fact it's an #Entity.
So in fact, I got in my project 2 classes who look the same (same attributes, same methods) but for different puprose.
IMO, in this case the DTO class is useless and increase application complexity because all I do with DTO class I can do it with my POJO class and moreover, for a single type of object I have to maintain at least 2 classes (the DTO and POJO), for instance if I add an attribute I have to add this attribute in both classes.
I'm not an expert and I'm questionning about my thoughts; what do you think about it ?
This answer is a replica of what can be found on stack exchange. IMHO the OP should be closed for being posted in the wrong forum. It's currently also attracting opinionated answers, though not necessarily so, and isn't tied to java in any particular way.
DTO is a pattern and it is implementation (POJO/POCO) independent. DTO says, since each call to any remote interface is expensive, response to each call should bring as much data as possible. So, if multiple requests are required to bring data for a particular task, data to be brought can be combined in a DTO so that only one request can bring all the required data. Catalog of Patterns of Enterprise Application Architecture has more details.
DTO's are a fundamental concept, not outdated.
What is somewhat outdated is the notion of having DTOs that contain no logic at all, are used only for transmitting data and "mapped" from domain objects before transmission to the client, and there mapped to view models before passing them to the display layer. In simple applications, the domain objects can often be directly reused as DTOs and passed through directly to the display layer, so that there is only one unified data model. For more complex applications you don't want to expose the entire domain model to the client, so a mapping from domain models to DTOs is necessary. Having a separate view model that duplicates the data from the DTOs almost never makes sense.
However, the reason why this notion is outdated rather than just plain wrong is that some (mainly older) frameworks/technologies require it, as their domain and view models are not POJOS and instead tied directly to the framework.
Most notably, Entity Beans in J2EE prior to the EJB 3 standard were not POJOs and instead were proxy objects constructed by the app server - it was simply not possible to send them to the client, so you had no choice about haing a separate DTO layer - it was mandatory.
Although DTO is not an outdated pattern, it is often applied needlessly, which might make it appear outdated.
From Java guru Adam Bien:
The most misused pattern in the Java Enterprise community is the DTO. DTO was clearly defined as a solution for a distribution problem. DTO was meant to be a coarse-grained data container which efficiently transports data between processes (tiers). ~ Adam Bien
From Martin Fowler:
DTOs are called Data Transfer Objects because their whole purpose is to shift data in expensive remote calls. They are part of implementing a coarse grained interface which a remote interface needs for performance. Not just do you not need them in a local context, they are actually harmful both because a coarse-grained API is more difficult to use and because you have to do all the work moving data from your domain or data source layer into the DTOs. ~ Martin Fowler
Here is a Java EE specific example of a common but incorrect use of the DTO pattern. If you're unfamiliar with Java EE, you just need to know the MVC pattern: a "JSF ManagedBean" is a class used by the View, and a "JPA Entity" is the Model in the MVC pattern.
So, for example, say you have a JSF ManagedBean. A common question is whether the bean should hold a reference to a JPA Entity directly, or should it maintain a reference to some intermediary object which is later converted to an Entity. I have heard this intermediary object referred to as a DTO, but if your ManagedBeans and Entities are operating within the same JVM, then there is little benefit to using the DTO pattern.
Futhermore, consider Bean Validation annotations (again, if you're unfamiliar with Java EE, know that Bean Validation is an API for validating data). Your JPA Entities are likely annotated with #NotNull and #Size validations. If you're using a DTO, you'll want to repeat these validations in your DTO so that clients using your remote interface don't need to send a message to find out they've failed basic validation. Imagine all that extra work of copying Bean Validation annotations between your DTO and Entity, but if your View and Entities are operating within the same JVM, there is no need to take on this extra work: just use the Entities.
The Catalog of Patterns of Enterprise Application Architecture provides a concise explanation of DTOs, and here are more references I found illuminating:
HOW TO DEAL WITH J2EE AND DESIGN PATTERNS
How to use DTO in JSF + Spring + Hibernate
Pros and Cons of Data Transfer Objects Martin Fowler's description of DTO
Martin Fowler explains the
problem with DTOs. Apparently they were being misused as early
as 2004
Most of this comes down to Clean Architecture and a focus on separation of concerns
My biggest use-case for the entities is so i don't litter the DTO's with runtime variables or methods that i've added in for convenience (such as display names / values or post-calculated values)
If its a very simple entity then there isn't so much of a big deal about it, but if you're being extremely strict with Clean then there becomes a lot of redundant models (DTO, DBO, Entity)
Its really a preference in how much you want to dedicate to strict Clean architecture
https://medium.com/android-dev-hacks/detailed-guide-on-android-clean-architecture-9eab262a9011
There is an advantage, even if very small, to having a separation of layers in your architecture, and having objects "morph" as they travel through the layers. this decoupling allows you to replace any layer in your software with minimal change, just update the mapping of fields between 2 objects and your all set.
If the 2 objects have the same members...well, then that's what Apache Commons BeanUtils.copyProperties() is for ;)
Other people have already informed you of the benefits of DTO, here I will talk about how to solve the trouble of maintaining one more DTO version object.
I deveploy a library beanKnife to automatically generate a dto. It will create a new class base the original pojo. You can filter the inherited properties, modify existing properties or add new properties. All you need is just writing a configuration class, and the library will do the left things for you. The configuration support inheritance feature, so you can extract the common part to simpify the configuration even more.
Here is the example
#Entity
class Pojo1 {
private int a;
#OneToMany(mappedBy="b")
private List<Pojo2> b;
}
#Entity
class Pojo2 {
private String a;
#ManyToOne()
private Pojo1 b;
}
// Include all properties. By default, nothing is included.
// To change this behaviour, here use a base configuration and all other final configuration will inherit it.
#PropertiesIncludePattern(".*")
// By default, the generated class name is the original class name append with "View",
// This annotation change the behaviour. Now class Pojo1 will generate the class Pojo1Dto
#ViewGenNameMapper("${name}Dto")
class BaseConfiguration {
}
// generate Pojo1Dto, which has a pojo2 info list b instead of pojo2 list
#ViewOf(value = Pojo1.class)
class Pojo1DtoConfiguration extends BaseConfiguration {
private List<Pojo2Info> b;
}
// generate Pojo1Info, which exclude b
#ViewOf(value = Pojo1.class, genName="Pojo1Info", excludes = "b")
class Pojo1InfoConfiguration extends BaseConfiguration {}
// generate Pojo2Dto, which has a pojo1 info b instead of pojo1
#ViewOf(value = Pojo2.class)
class Pojo2DtoConfiguration extends BaseConfiguration {
private Pojo1Info b;
}
// generate Pojo2Info, which exclude b
#ViewOf(value = Pojo2.class, genName="Pojo2Info", excludes = "b")
class Pojo2InfoConfiguration extends BaseConfiguration {}
will generate
class Pojo1Dto {
private int a;
private List<Pojo2Info> b;
}
class Pojo1Info {
private int a;
}
class Pojo2Dto {
private String a;
private Pojo1Info b;
}
class Pojo2Info {
private String a;
}
Then use it like this
Pojo1 pojo1 = ...
Pojo1Dto pojo1Dto = Pojo1Dto.read(pojo1);
Pojo2 pojo2 = ...
Pojo2Dto pojo2Dto = Pojo2Dto.read(pojo2);
I am currently working on several solutions to redesign a web application based on a database that is shared between this application and other running services.
The actual application uses NodeJS, and basically processes data after having exctracted too much information from a table in the database. I think this is wrong, because we should only ask the database for the data we need, and limit processing on the server as these processes imply long loading time for end users.
So I thought I would build a Java API instead, that would use objects that can be easily used by the front part of the application, and use Hibernate or an equivalent component to extract necessary information from database.
But the problem is that the database over which I would build this API, while supposed to be relational (it's postgreSQL), is actually composed of tables that do not communicate between each other : there are no joins between tables, hence no cascade on modifiying related objects. Furthermore, the tables do not correspond directly to objects used in the application. They are more like "super objects" that would contain other sub-objects in a Java model.
Problem is, I cannot recreate a "cleaner" database as it is used by other services (which is probably why it is so weirdly organised, by the way). I should use it as it is, and map the redesigned application to it. I could be allowed to redesign some tables to make them "more relational", but this should have no implications for the other services. That would imply to drastically rewrite some SQL functions, and I am not sure that it is a very efficient solution. That being say, I am not very experienced on writing SQL functions, so maybe that could be a solution in the end.
So, to put it all in a nutshell, what could I do to build an object oriented model using Java, or any other technology that you could think of, to redesign properly the application, without throwing the database or modifying it drastically ?
Any suggestion or lead of research would be greatly appreciated. Also, please tell me if I am not being precise enough, and I will try to improve my question.
Use JPA to map your database records into entities.
This wiki page gives quite a few samples of advanced uses :
multiple tables for an entity :
#Entity
#Table(name="EMPLOYEE")
#SecondaryTable(name="EMP_DATA",
pkJoinColumns = #PrimaryKeyJoinColumn(name="EMP_ID", referencedColumnName="ID")
)
public class Employee {
...
#Column(name="YEAR_OF_SERV", table="EMP_DATA")
private int yearsOfService;
#OneToOne
#JoinColumn(name="MGR_ID", table="EMP_DATA", referencedColumnName="ID")
private Employee manager;
...
}
multiple kind of entities in single table (this sample is mine, there was no code on the wiki ; let's hope I didn't mess it up !) :
#Inheritance
#DiscriminatorColumn(name="DISCRIMINATING_COLUMN")
#Table(name="SOME_TABLE")
public class Generic { ... }
// only maps records from SOME_TABLE where DISCRIMINATING_COLUMN=SOME_VALUE
#Entity
#DiscriminatorValue("SOME_VALUE")
public class firstSpecificType { ... }
// only maps records from SOME_TABLE where DISCRIMINATING_COLUMN=OTHER_VALUE
#Entity
#DiscriminatorValue("OTHER_VALUE")
public class secondSpecificType { ... }
entities from proc calls :
// This stored procedure returns a result set and has one input parameter.
#NamedStoredProcedureQuery(
name = "ReadAddressById",
resultClasses = Address.class,
procedureName = "READ_ADDRESS",
parameters = {
#StoredProcedureParameter(mode=javax.persistence.ParameterMode.IN, name="P_ADDRESS_ID", type=Long.class)
}
)
#Entity
public class Address {
...
}
and many others.
I have been designing spring rest apis using standard MVC architecture like domain layer as POJOs and repositories to fetch domain data from db tables. So far these entities were isolated so the design acted as separate RestController, Service, and Repository flow for each entity.
I have been looking to understand the best practice when it comes to association in domain objects i.e., ORM. For example, lets take following pseudocode to illustrate domain classes (only for the purpose to express the design in question. I have not provided complete classes):
public class Customer {
#Column
private int id;
#Column;
private String name;
#OneToMany
private List<Order> orders;
//...getters setters
}
public class Order {
#Column
private int id;
#Column;
private String orderNumber;
#OneToMany
private List<Product> products;
#ManyToOne
private Customer customer;
//...getters setters
}
public class Product {
#Column
private int id;
#Column;
private String productName;
#ManyToOne
private Order order;
//...getters setters
}
The dilemma I have from designing perspective. I have following approaches that very well all be incorrect:
Define one RestController for customer and provide all the api resources like /customers, /customers/id/orders, /customers/id/orders/id/products etc. Have one Service that takes care of working with these domains. Have separate JPARepository for EACH domain. The "keep it simple" thing here is that I have separete repository for each domain so I just have to provide query methods in corresponding Repository class in order to find details for a specific domain i.e., fetch orders for a given customer Id. However, that makes me think killing the purpose of using ORM model because I am fetching individual domains through their Repository classes. This option will make all 3 repository classes wired in the service class and that also I think is not a good design. 3 might looks okay here but I have 6 to 7 domains in the ORM graph in my actual requirements so that would mean autowiring 6 repositoris in one service class.
One RestController and one Service class as in above option but the Repository class is single too. The Repository is created only for Customer domain. In this way I retrieve Customers with other domaims lazy loaded. This is to fulfil a GET request of "/customers". To fulfil a GET request of "/customers/id/orders" I will again use Customer Repository, retrieve customer for the given Id and then return list of Orders. Further, for a GET request of "/customers/id/orders/id/products" , I will require writing a manual data fetching mechanism in Customer domain so that it takes care of retrieving list of products for a given customerId and orderId. This way I use one Repository, satisfying the purpose of using ORM but then adding manual fetching data methods in Customer domain. Another negative I see is that I need to get complete list of orders in a customer domain even if I have customerId and orderId available. I would have fetched one single order based on customerId and orderId has I used a separate repository for Order.
Both are incorrect and there exists a better approach.
I have looked through spring docs for repository and hibernate docs for ORM. I went through multiple tutorials for one-to-many mappings with spring data rest but I found mixed approaches in different tutorials.
This question will look duplicate to you as I have read multiple posts on stackoverflow regarding this design concern but none of the answers give me a reasoning for the trade offs and options I mentioned above. Hence, I am reposting this question.
It is a mixed approach. e.g. in your case the product entity need not have a #ManyToOne relation with the Order. Imagine if your product is part of 1 million orders! How many time will you query a product to find orders? You will query findOrdersByProduct(Product) rather than findProductByOrder(Order)
think w.r.t your usecase. Sometimes it makes sense to have one directional mapping if you will never fetch the information other than from the owner of the relationship
Think about the amount of data that you will fetch (including the joins) if you query an entity.
e.g if i am fetching an organization do i need to fetch all its employees? your system will go for a toss (lazy loading will save you most of the time but if you have an Angular then it will bind and fetch the entire model). But it does make sense to have many to one relationship with an org from the employee entity.
Preliminary Info
I'm currently trying to integrate Hibernate with my team at work. We primarily do Java web development, creating webapps that provide data to clients. Our old approach involves calling stored procedures with JDBC (on top of Oracle boxes) and storing their results in beans. However, I've heard a lot about the benefits of integrating Hibernate into a development environment like ours so I'm attempting to move away from our old habits. Note: I'm using the Hibernate JPA annotation approach due to simplicity for team adoption's sake.
Specific Problem
The specific issue I'm having currently is using Hibernate with normalized tables. We have a lot of schemas structured like so:
StateCodes (integer state_code, varchar state_name)
Businesses (integer business_id, varchar business_name, integer state_code)
I want to be able to have a single #Entity that has all of the "Businesses" fields, except instead of "state_code" it has "state_name". To my understanding, Hibernate treats #Entity classes as tables. The #OneToMany, #OneToOne, #ManyToOne annotations create relationships between entities, but this is a very simplistic, dictionary-like lookup and I feel like it doesn't apply here (or might be overkill).
One approach I've seen is
#Formula("(select state_name from StateCodes where Businesses.state_code = state_code)")
private String stateCode;
But, given Hibernate's perk of "avoiding writing raw SQL", this seems like bad practice. Not to mention, I'm extremely confused about how Hibernate will then treat this field. Does it get saved on a save operation? It's just defined as a query, not a column, after all.
So what is the best way to accomplish this?
I do not see any reason not use the standard JPA mappings in this case. Short of creating a database view and mapping an entity to that (or using the non-JPA compliant #Formula) then you will have to map as below.
Unless you are providing a means for the State to be changed then you do not need to expose the State entity to the outside world: JPA providers do not need getters/setters to be present.. Neither do you need to Map a State to Businesses:
#Entity
#Table(name = "Businesses")
public class Business{
//define id and other fields
#ManyToOne
#JoinColumn(name = "state_code")
private State state;
public String getStateName(){
return state.getName();
}
}
#Entity
#Table(name="StateCodes")
public class State{
//define id and other fields.
#Column(name = "state_name")
private String stateName;
public String getStateName(){
return stateName;
}
}
I have following entitys:
#Entity
#Inheritance
#DiscriminatorColumn(name = "TYPE")
#DiscriminatorValue("Company")
public class Company {
... (lot of attributes)
}
#Entity
#DiscriminatorValue("Company")
public class LargeCompany extends Company {
... (a few not required attributes)
}
The Company entity lies in a separate project and should be extendable (usually just by one subclass).
When I use #Inheritance by default JPA creates only one table with all attributes from Company and all sub classes. To separate all these different types of instances JPA
uses the #DiscriminatorValue which is usually different for each class.
I realized that it doesn't cause problems if I use same #DiscriminatorValue for both classes (entities). That would make it much easier to use:
The separat project can be responsible for creating Companies and storing them (UI, Validation, etc.). In the next step my project could load these Companies and without
an additional step I get LargeCompany objects.
I verified with several integration tests that this works (when entityManager is cleared) but I'm not sure if I can really rely on that "feature"? Is there probably a better way?
Btw. I'm using hibernate 4.2.0
one of the working tests:
#Test
public void test() {
Company company = new Company("TEST");
em.persist(company);
em.flush();
em.clear(); // required!!
company = em.createQuery("from Company").getFirstResult();
assertEquals(LargeCompany.class, company.getClass());
}
Are you trying to convert one Object in one application to another object in another machine? In this case, it will work. If we talk about its background, in backend (in DB) it create one column for discrimination of row and that row be form to particular java object based on that discrimination value. As you are using same discrimination value in two application accessing same DB, its actually transporting the object from one application to another application. But, If you try to use same discrimination value in single application then you will be in trouble. Firstly, it should give error and if its not giving error then its converted one of your object to another object without your knowledge. So, be careful when using it in same application.