Difference between JPA Entity and Hibernate Entity - java

When I annotate a class with #Entity and try to resolve the dependencies, I get to choose the package between two different packages, javax.persistence.Entity and org.hibernate.annotations.Entity
The javax package is JPA's entity-annotation, but why is there a hibernate entity-annotation and difference does it have with JPA's annotation? Is it just an extension to allow more attributes to be defined?

org.hibernate.annotations.Entity has some extra attributes that javax.persistence.Entity has not standarized. The extra features will only work if using hibernate's AnnotationConfiguration directly or if hibernate is the JPA provider.
from the FAQ:
edit: new link the specific question:
edit: new link the answer:
I use #org.hibernate.annotations.Entity and get an Unknown entity exception
Always import #javax.persistence.Entity
#org.hibernate.annotations.Entity completes #javax.persistence.Entity but is not a replacement
For instance, there is an attribute called optimisticLock, which tells hibernate whether to use the standard version column or to compare all columns when updating. This behavior is not in the JPA spec, so in order to configure it, you must use hibernate specific extension found in their own annotation.
Like this:
#Entity
#org.hibernate.annotations.Entity(optimisticLock=OptimisticLockType.ALL)
public class MyEntity implements Serializable {
...
}

#org.hibernate.annotations used in your project, if suppose you want to use JDBC template or ibatis we need to change the code. if we use javax.persistence there is no need to change the code. This is the main difference between org.hibernate.annotations and javax persistence

I'm not sure about the differences but I am sure that if you have the Hibernate jars in your classpath you are using Hibernate JPA. Hibernate provides an implementation of JPA. Even though you are using the javax.persistence package you are using Hibernate JPA.
The difference could be only in the naming. They might provide the same classes both in the Hibernate package space and the javax package space.

Related

Hibernate Implicit Naming Strategy is ignored when using multiple datasources

According to the following tutorial, I created two configruation files for two database sources: Baeldung-JPA-Multiple-Databases
It works fine, but it seems that the implicit naming strategy is ignored. That means that an Entity CustomerContact is not mapped to a table customer_contact.
I tried to add the following two properties, but nothing changes:
public LocalContainerEntityManagerFactoryBean primaryEntityManager() {
...
properties.put("hibernate.naming.implicit-strategy", "org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy");
properties.put("hibernate.naming.physical-strategy", "org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy");
em.setJpaPropertyMap(properties);
...
}
One solution would be to use the name attribute of the persistence annotations, like
#Entity(name = "customer_contact"), but I would like to avoid that and use the implicit mapping instead.
The answer can be found here: Can't set JPA naming strategy after configuring multiple data sources (Spring 1.4.1 / Hibernate 5.x)
The needed properties are:
props.put("hibernate.physical_naming_strategy", SpringPhysicalNamingStrategy.class.getName());
props.put("hibernate.implicit_naming_strategy", SpringImplicitNamingStrategy.class.getName());

JPA [Eclipselink] - How to refresh metadata of Dynamic entities created?

I got to know about possibility of Dynamic entity creation in eclipselink from here. And I'm trying to create Dynamic entities and map them to static entities which are already present in the same persistence unit as described in the examples given here.
I'm using refreshMetadata(with empty map of properties) of EntityManagerFactoryImpl to refresh metadata.
But the the dynamic entities are not getting listed in the metamodel of entitymanager factory.
Can somebody let me know where am I going wrong?
I expect they won't, as the Dynamic entity api adds mappings to the native EclipseLink session, while the JPA metamodel is build from JPA mappings. refreshMetadata is used to rebuild the native EclipseLink session using any new JPA metadata (orm.xml etc), but does not go the other way.
I was able to refresh the metamodel by adding a new metamodel with the current session by the following code snippet:
Metamodel metamodel = new MetamodelImpl((AbstractSession) dynamicHelper.getSession());
((EntityManagerFactoryImpl) emf).setMetamodel(metamodel);
Though this didn't solved my main problem, it solved the problem I've asked here.

How to tell Hibernate annotation #Column to be case-sensitive?

I'm trying to do a simple SELECT query in a table named ECM (in uppercase) on a Sybase db with Hibernate. I've annotated my DBO this way :
#Entity
#Table(name="ECM")
public class RelationshipDbo {
...
}
However, I'm facing a "table not found" error : the generated SQL has the table name in lowercase. I cannot change the database configuration to tell it to be case-insensitive.
I've also tried putting quotes like this :
#Table(name="`ECM`")
and this :
#Table(name="'ECM'")
Result : the quotes are added in the query, but the table name is still converted from uppercase to lowercase.
Technical information :
Hibernate 4.3
JPA 1.2
org.hibernate.dialect.SybaseDialect
Have you guys any idea?
EDIT: Also tried this Hibernate changes #Table(name) to lowercase
Then my columns names and table name are automatically quoted, but the names still get lowercased.
I think I have your answer:
Basically, you need to change the naming strategy for you JPA provider. How you do this will depend on how you setup your project.
In my case, using spring boot data I set a property in my application.properties to
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.EJB3NamingStrategy
Without more details from you I can't give more specifics on how to do this.
My goal is a little different since was trying to create tables upper case and hibernate created them in lower case. Also i was using MySQL not Sybase.
But for me quoting the names like this worked:
#Entity
#Table(name="\"ECM\"")
public class RelationshipDbo {
...
}
Then tables were created upper case. Maybe that helps also for the queries.
What is your Sybase db version ?
SybaseDialect has been deprecated in Hibernate 3.5 and then refactored since Hibernate 4.1 with a bunch of subclasses matching different versions of Sybase. Have you tried one of the subclasses to see if it makes any difference?
org.hibernate.dialect.Sybase11Dialect
org.hibernate.dialect.SybaseAnywhereDialect
org.hibernate.dialect.SybaseASE15Dialect
Try this:
Use backticks as in #Table(name="`ECM`")?
This must work from Hibernate point. If not then problem should be in DB (if i'm not wrong)

JPA equivalent for Hibernate filters

Does an equivalent for the Hibernate filters exist in the JPA?
The following hibernate annotation can be for example used in order to define a filter:
#Entity
#FilterDef(name="minLength", parameters=#ParamDef( name="minLength", type="integer" ) )
#Filters( {
#Filter(name="betweenLength", condition=":minLength <= length and :maxLength >= length"),
#Filter(name="minLength", condition=":minLength <= length")
} )
public class Forest { ... }
I would like to use something equivalent from JPA in order to restrict read access to some entities. How it can be done using clean JPA, without Hibernate annotations?
I didn't find any serious and reliable solution.
I analysed the "JPA Security" project. However, its home page was last updated two years ago, its last version is 0.4.0 and it doesn't seem to be a reliable solution. It's not a standard and it is not popular.
Other alternative in Hibernate which can be used in my case to restrict read access to an entity is the Hibernate Interceptor API - the following interface method can be implemented in order to append a SQL string which contains some additional conditions:
org.hibernate.Interceptor.onPrepareStatement(String sql)
or the following method can be overriden:
org.hibernate.EmptyInterceptor.onPrepareStatement(String sql)
I found out that there are some JPA event callbacks and annotations, e.g. #PostLoad. However, none of these can be used in my case, because I need something to restrict access to entities based on some conditions (user role).
Anyone knows how it can be done using JPA standards?
It seems to me that you are attempting to perform validations on entity objects. You have a few options to accomplish this.
The first would be to use the Java Validations API and its associated validations. This is the recommended approach with Java EE, of which JPA is a part. For example, you could write your entity class as follows:
#Entity
class Person {
#NotNull
#Size(min = 5, Max = 50)
String name;
}
Now, every time you attempt to persist an instance of Person, the JPA provider will automatically validate the instance, provided there is a Java Validator on the classpath. Validation errors will be thrown as runtime exceptions and can be used to rollback transactions. It is also possible to invoke a validator manually, collect any validation errors and transform them into user-friendly messages if required.
The other (probably dirty) option is to use the JPA Event Listeners, perform validations and throw an exception if a validation fails. This will terminate the JPA operation immediately and rollback any transactions.

Share class with annotations

I want to use a simple class with hibernate annotations in a non db project.
I dont wanna dublicate the code and remove annotations.
Is there a way for doing this like using annotations in subclass for parent class's attributes. So i can share the parent class.
Any help would be great, thanks.
Edit:
For example: I have a class:
#Entity
#Table(name = "Sample")
Class Sample{
#Column(name = "attr1")
private String attr1;
// getter setters etc.
}
This class works good for a java project with db dependencies set.
But I serve a restful service with this class.
My client app do not need any db related functions so I dont include any db related jars.
So this is my problem I want to use same classes since both are common for two projects. But I do not need db jars which leads to #Entity annotations to compile errors.
If there is some way to do this, I would be very happy.
Thanks alot.
use hibernate validation groups
Basic Validation Example
create 2 validation groups and use one of them for db project and other for not db project

Categories