Using #PersistenceContext and EntityManager for several schemas - java

I am currently working on a JavaSE project that I would like to build in the most effective way. My project is an employeeManagementSystem which has several schemas. For example I have one schema called employees which contains employee data and another schema called company which contains the company data.
Currently I have implemented my entities and tested these using hibernate.cfg.xml to make sure they are implemented correctly. For example, one such entity in the employee schema is
#Entity
#Table(name="employees", uniqueConstraints= {
#UniqueConstraint(columnNames="idEmployees"),
#UniqueConstraint(columnNames="idCardNumber"),
#UniqueConstraint(columnNames="niNumber")
})
public class Employee {
#Id
#GeneratedValue
#Column(unique=true, nullable=false, updatable=false)
private int idEmployees;
#Column(unique=true, nullable=false, updatable=false)
#Size(min=1, max=15)
private String idCardNumber;
#Column(unique=true, nullable=false, updatable=false)
#Size(min=1, max=15)
private String niNumber;
#Column(nullable=false, updatable=false)
#Size(min=1, max=20)
private String name;
#Column(nullable=false)
#Size(min=1, max=20)
private String surname;
// Other class variables
//Constructors
//getters & setters
}
I an now trying to use an EntityManager to manage my schemas. My persistence.xml for the employee schema is
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="EmployeesDAO" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.shopmanagementsystem.employeesdao.entities.Employee</class>
//Other classes in this schema
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="root"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/employees"/>
</properties>
</persistence-unit>
</persistence>
I want to create a Service and ServiceImpl class to manage the processes related to the entities.
Q1) Should I have a Service and ServiceImpl for each entity?
Some of my questions were answered already in a previous post JPA EntityManager Construction
Q2) I further asked about using #PersistenceContext and was kindly advised to ask another question with a more detailed description of my project.
I am happy to add more details if I've left anything out and thank you for your advice and help.

Q1) Should I have a Service and ServiceImpl for each entity?
Not necessarily. Based on the name of the persistence unit: EmployeesDAO, I'm assuming that Service and ServiceImp are intended to implement DAO pattern, right? In this context you have to offer a contract (INSERT / UPDATE/ DELETE / QUERY) just for those entities that actually require it. For example you can have a table called Category which has a relationship with Employee like this:
#Entity
#Table(name="categories")
public class Category implements Serializable {
...
#Id private BigInteger idCategory;
#Basic private String description;
...
}
#Entity
#Table(name="employees")
public class Employee implements Serializable {
...
#ManyToOne
#JoinColumn(name="idcategory", referencedColumnName="idcategory")
private Category category;
...
}
In this example you would have a Service to manage Category entities only if you need to. If those entities are managed by another application then you just need to have read privileges on categories table so the entity manager can map this data and that's it.
Q2) I further asked about using #PersistenceContext and was kindly advised to ask another question with a more detailed description of my
project.
First of all please beware that #PersistenceContext annotation is intended to be used with container-based persistence, as part of a Java EE application. You cannot use this annotation in plain Java SE platform.
On the other hand it doesn't mean you can't use JPA. Yes, it's perfectly possible, but you have to take care of the whole entity managers life-cycle. It is a common practice in this case to implement design patterns (such as Abstract Factory or Factory method or Singleton) in order to instantiate/access your entity managers manually.
In addition if you want to develop the top level layers of your application using Java SE and use container-managed persistence, then you can code the persistence layer using JPA and Enterprise JavaBeans architecture. This approach is not simple but has several advantages:
You can offer the persistence layer as a service through EJB modules.
Database connections and pools can be managed by the EJB container. This is extremely useful to separate database connection info from persistence.xml file.
As already mentioned, the EJB container will manage the whole entity manager life-cycle.
You can go further and leave container use Java Transaction API so you can forget (more or less) about transactional stuff.
Other comments
I know that posted persistence.xml is probably just an example but I have to mention that connect to the database as root user is not a good practice at all. Due to security reasons you should have several users with the right privileges to access your database, and likely none of them will ever need super-user privileges.
Finally, applications design is a really broad topic and it can be simple or complex based on your requirements. In addition there are several frameworks/technologies that can be used and is very very easy to get lost if you don't have any experience. My suggestion if you never did something like this before is to start with a very basic application and then go further.

Related

#version annotation not working properly in jpa/eclipselink

I have a base entity class
where one of the fields(Timestamp) has #version attribute, so Jpa will automatically increment the value.
But, sometimes the timestamp value is not getting updated, the edited date is less than the created date, but this should never happen theoretically.
I am not setting the edited value programmatically.
Here is my entity class:
public class BaseEntity implements Serializable {
#Column(name = "CREATED")
private Timestamp created;
#Column(name = "EDITED")
#Version
private Timestamp edited;
// other fields, getters and setters
}
Have read many articles about this #version annotation, but I don't understand why this value will not update, what are the reasons behind this.
If some one help me, would be great
Thanks
Here are some basic guidelines:
Check if you imported the right package javax.persistence.Version.
Use obj = entityManager.merge(obj); when saving changes to already persisted entities.
Never change the value of your version-field manually. The entity-manager will take care of it.
For further debugging edit your persitence.xml and add following lines to properties:
<property name="eclipselink.logging.level" value="FINE"/>
<property name="eclipselink.logging.parameters" value="true"/>
<property name="eclipselink.logging.sql.level" value="FINE"/>
This will enable fine logging and generate a lot of output. You'll be able to see the update queries and what exactly happens.

JPA 2.0 : Issue : orphanRemoval throwing integrity violations using Open JPA

Request assistance with the strange issue of cascade removal with JPA 2.0.Please find below the details
I'm using JPA bundled with IBM Websphere 8.5 that comes along with RAD.
The issue I'm facing is when I try deleting an entity having a one to Many relationships with another entity, I always encounter the ORA-02292: integrity constraint violation. Below are the specific parts highlighting the relationship between two entities - FeeForService and FeeForServiceProduct.
FeeForService has a One to Many Relationship with FeeForServiceProduct.
Please note the issue occurs when I run it on the Websphere server. I've tried running the below as a standalone program and it works with the workarounds of putting a cascade property at the many end and invoking em.remove() twice
#Entity
#Table(name="FEE_FOR_SERVICE")
public class FeeForService implements Serializable {
private static final long serialVersionUID = 1L;
....
....
//bi-directional many-to-one association to FeeForServiceProduct
#OneToMany(mappedBy="feeForService",cascade={CascadeType.ALL},orphanRemoval=true)
private Set<FeeForServiceProduct> feeForServiceProducts;
....
}
#Entity
#Table(name="FEE_FOR_SERVICE_PRODUCT")
public class FeeForServiceProduct implements Serializable {
....
....
//bi-directional many-to-one association to FeeForService
#ManyToOne(cascade={CascadeType.ALL})
#JoinColumn(name="FEE_FOR_SERVICE_ID")
private FeeForService feeForService;
}
Initially I had tried with only CASCADE=CASCADEType.ALL property but as it didn't work out had to use orphanRemoval.
The error that I receive is java.sql.SQLIntegrityConstraintViolationException: ORA-02292: integrity constraint violated. Child Record found.
Below is the code sample I have used for deleting the FFS entity, assuming by setting orphanRemoval to true I don't have to explicitly delete the FFSProduct entity. But that doesn't seem to be working
public void testDeleteFFS(){
EntityManagerFactory entityManagerFactory=Persistence.createEntityManagerFactory("DummyTestService");
EntityManager em=entityManagerFactory.createEntityManager();
long crVO=3658;
List<FeeForService> ffsExisting=(List<FeeForService>) em.createQuery("SELECT i FROM FeeForService i INNER JOIN i.customerRequest u where u.customerRequestId="+crVO).getResultList();
System.out.println("begin of delete");
//for deleting child entity FFSProduct
for(FeeForService ffsCandidate:ffsExisting){
em.getTransaction().begin();
em.remove(ffsCandidate);
em.getTransaction().commit();
}
/*for deleting parent entity FFS as the FFSProduct entity was retained when a single for loop was used*/
for(FeeForService ffsCandidate:ffsExisting){
em.getTransaction().begin();
em.remove(ffsCandidate);
em.getTransaction().commit();
}
System.out.println("End of delete");
}
Is there any way with JPA 2.0 where I can delete all the dependent entities by only invoking a remove operation on the parent entity and if so,please point out where I'm going wrong as my understanding until now is that this must be possible by setting orphanRemoval to true on the owning entity.
Also please note that the Cascade = CascadeType.ALL was given at the FFS product or the many end of the relationship as the solution was not working without it.(as I mentioned at the top it strangely seems to work when running as a standalone)
My persistence.xml properties are as below
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="DummyTestService" transaction-type="RESOURCE_LOCAL" >
<class>FeeForService</class>
<class>FeeForServiceProduct</class>
<validation-mode>NONE</validation-mode>
<properties>
<property name="openjpa.ConnectionURL" value="jdbc:oracle:thin:#xxxx"/>
<property name="openjpa.ConnectionDriverName" value="oracle.jdbc.OracleDriver"/>
<property name="openjpa.ConnectionUserName" value="xxxx"/>
<property name="openjpa.ConnectionPassword" value="xxxx"/>
<property name="openjpa.RuntimeUnenhancedClasses" value="supported" />
<!-- <property name="openjpa.DynamicEnhancementAgent" value="true"/> -->
<property name="openjpa.Log" value="File=D:\XXXX\JPAstandalonelog,DefaultLevel=WARN, Tool=INFO,SQL=TRACE"/>
</properties>
</persistence-unit>
Thanks in Advance

Correct JPA Annotation for PostgreSQL's text type without Hibernate Annotations

I'm developing an application using:
Java 1.7
JPA (included in javaee-api 7.0)
Hibernate 4.3.8.Final
PostgreSQL-JDBC 9.4-1200-jdbc41
PostgreSQL 9.3.6
And I would like to use the PostgreSQL text datatype for some String attributes. As far as I know, in JPA this should be the correct annotation, to use text in PostgreSQL:
#Entity
public class Product{
...
#Lob
private String description;
....
}
When I annotate my entity like this, I run into errors which look like this:
http://www.shredzone.de/cilla/page/299/string-lobs-on-postgresql-with-hibernate-36.html
In short: It seems that hibernate and jdbc go not hand in hand for clob/text-types.
The solution described is working:
#Entity
public class Product{
...
#Lob
#Type(type = "org.hibernate.type.TextType")
private String description;
...
}
But this has a significant downside: The source code needs hibernate at compile time, which should be unnecessary (That's one reason for using JPA in the first place).
Another way is to use the column annotation like this:
#Entity
public class Product{
...
#Column(columnDefinition = "text")
private String description;
...
}
Which works nicely, BUT:
Now I'm stuck with databases which have a text type (and is also called text ;) ) and if another database will be used in the future the annotations can be overlooked easily. Thus the possible error can be hard to find, because the datatype is defined in a String and therefore can not be found before runtime.
Is there a solution, which is so easy, I just don't see it? I'm very sure that I'm not the only one using JPA in combination with Hibernate and PostgreSQL. So I'm a little confused that I can't find more questions like this.
Just to complete the question, the persistence.xml looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="entityManager">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.app.model.Product</class>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver" />
<property name="javax.persistence.jdbc.url"
value="jdbc:postgresql://localhost:5432/awesomedb" />
<property name="javax.persistence.jdbc.user" value="usr" />
<property name="javax.persistence.jdbc.password" value="pwd" />
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />
<property name="hibernate.jdbc.use_streams_for_binary" value="false" />
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="show_sql" value="true" />
</properties>
</persistence-unit>
</persistence>
UPDATE:
This problem is more or less equivalent with this question, the picked answer is the second way to do it described in this question, which I don't like due to the hibernate runtime dependency:
store strings of arbitrary length in Postgresql
This seems to be kind of related to: https://hibernate.atlassian.net/browse/JPA-48
Since the text type is not a part of the SQL standard there is no official JPA way I guess.
However, the text type is quite similar to varchar, but without the length limit. You can hint the JPA implementation with the length property of #Column:
#Column(length=10485760)
private String description;
Update: 10 MiB seems to be the maximum length for varchar in postgresql. The text is almost unlimited, according the documentation:
In any case, the longest possible character string that can be stored
is about 1 GB.
I just had to add this annotation:
#Column(columnDefinition="TEXT")
It did not work on its own. I had to recreate the table in the database.
DROP TABLE yourtable or just alter column type to text with ALTER TABLE statement
If you want to use plain JPA you could just remap the used CLOB type on the Dialect like this:
public class PGSQLMapDialect extends PostgreSQL9Dialect {
#Override
public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
if (Types.CLOB == sqlTypeDescriptor.getSqlType()) {
return LongVarcharTypeDescriptor.INSTANCE;
}
return super.remapSqlTypeDescriptor(sqlTypeDescriptor);
}
}
So it won't use the CLOB mapping from the JDBC driver which uses a OID for the column and stores/loads the text via large object handling.
This would just result in setString and getString calls on the createt text column on the Postgres JDBC Driver via the VarcharTypeDescriptor class.
I would go with simple private String description;. The column type is only a problem if you are generating the database from your code, because it will be generated as varchar instead of text.
It is great to code in database agnostic way, and without any JPA vendor specific things, but there are cases where this just isn't possible. If the reality is that you will have to support multiple database types with all their specifics, then you have to account for those specifics somewhere. One option is to use columnDefinition for defining column type. Another is to leave the code as it is, and just change the column type in the database. I prefer the second one.

How to change Persistence Unit dynamically?

I have a Spring MVC + Hibernate + JPA app. Also have 4 different Schemas in my db with similar tables. (for different companies) .
Now when I'm using my Hibernate app, can i switch Persistence Unit so
that I can use same the form (with the same content) to save data in
all four Schemas?
I'm aware that i can switch persistence unit at run time, but i want to be able to use the already loaded forms to save data to all four Schemas by changing the persistence unit.
I had similar problem some time ago.
I had 2 identical schemas - application had to persist to first or second depending on some logic.
It was pure Hibernate, but talking in terms of JPA I will suggest to have 4 persistence units defined in your persistence.xml:
persistence.xml
<persistence-unit name="PU1">
...
</persistence-unit>
<persistence-unit name="PU2">
...
</persistence-unit>
[...]
and DAO class that has injected EntityManager proxies - each for different PU:
#Repository
public class MyDaoImpl implements MyDao {
#PersistenceContext(unitName = "PU1")
private EntityManager em1;
#PersistenceContext(unitName = "PU2")
private EntityManager em2;
...
public void saveToPU1(MyEntity e) {
em1.persist(e);
}
public void saveToPU2(MyEntity e) {
em2.persist(e);
}
...
}
Of course em1 annotated with #PersistenceContext(unitName="PU1") is Spring's proxy to Hibernate session and becomes open and bound with current thread only if that thread tries to use it.
I am not sure to understand your problem: of course you can change the PersistentUnit used at runtime with the Persistence#createEntityManagerFactory(String persistenceUnitName) method.
But if you want to
save data to all four Schemas
Then you should repeat your operation (persist I guess) four times (for example in a private method taking the persistence unit name as parameter).
You could introduce a form cache if you want to reuse the already loaded forms, but this is a software architecture question.
As suggested in the Java EE 5 tutorial, on a software design point of view, having a form depending directly on the JPA layer is not a best practice. The other answer suggests it: a DAO could be the solution. All is about your DAOs lifecyle.
The Core JEE patterns book suggests it (the online reference only mentions briefly the topic, the printed book is better): associating DAOs with a Factory pattern is a good idea. You could recycle the EntityManagerFactory or anything you wish.

Validating Jpa Entities: In service or by lifecycle listeners

The question is where it is better (or in other words: where do you prefer) to put business validation logic of Jpa Entities.
Two ideas are:
In the EntityListener that before save or update would validate the entity
In the service that provides access to jpa persisting methods.
There are pros and cons of both.
When using approach No. 2 it is easier to test as you may just mock the jpa provider and test the validation logic. On the other hand with approach No. 1 the validation would happen at the same moment with validations like #NotNull etc.
I would love to know how do you solve validations in your projects and which is the better way to go.
Thanks.
Here's a general thumb rule that I follow:
When using bean validation, specify
rules that do not require dependencies
on other beans. The moment you depend
on another bean, get your service
layer to handle that dependency.
In other words, if you have a reference to a bean inside another, avoid putting in that #NotNull constraint. Your service layer is best used for that, for you're catching the violation much earlier, and at a more logical point (since other business validations would assume that the beans are available).
As an example, consider the following entity (apologies for it wont compile)
#Entity
public class User
{
#Id
private int id;
#NotNull
private String fullName;
#NotNull
private String email;
private Set<Role> roles; //No bean validation constraints here.
...
public boolean mapRoleToUser(Role role)
{ //Validation is done here. Including checks for a null role.
}
}
#Entity
public class Role
{
#Id
private int id;
#NotNull
private String name;
}
The service layer in this case, is the one that should validate whether the user has a role attached or not. Verification in the pre-persist or pre-update phase is a bit too late, especially when there is a distinct service layer that has business logic, and the rest of the business logic in the domain model (sadly, I haven't seen a good enough application with all of the logic in the domain model alone).

Categories

Resources