Different between #AttributeOverride and #AssociationOverride in JPA - java

What is the difference between #AttributeOverride and #AssociationOverride. Please explain me with the simple example.

From official documentation:
#AssociationOverride
Used to override a mapping for an entity
relationship
#AttributeOverride
Used to override the mapping of a Basic (whether explicit or default)
property or field or Id property or field.
Read official javadoc: is well explained with some example.

May be that is a bit more simple:
The #AttributeOverride annotation is used to override the mapping of property or field or Id property or field.
The #AssociationOverride annotation is used to override a many-to-one or one-to-one mapping of property or field for an entity relationship.
https://javabeat.net/eclipselink-jpa-annotations-attributeoverride-associationoverride/

Related

Using bean Validation in hibernate

I was wondering if it was possible to use Java Bean Validation in hibernate, and how they integrate with each other.
I have a stack that consists of a Jax-rs API, and JPA in my data layer.
I was wondering if I it could use Java Bean validation to validate my Hibernate Entities, without using Spring.
Could I use the annotations from hibernate along with the ones from the javax.validation.contraints together
for example:
#Column(nullable = false)
#Size(min =8, max = 12)
#NotNull(message = "Phone Number must be entered")
private String phoneNumber;
here I specify that I the column, can't be null through hibernate and the bean validation.
Is this a good practice?
Or is there an alternative to validating data in hibernate, without bean validation like such?
The Bean Validation specification integrates with Hibernate and all other implementations of the JPA 2.x specification. I explained that in great detail in my article How to automatically validate entities with Hibernate Validator.
Let me give a quick summary:
If you add an implementation of the Bean Validation specification, e.g., Hibernate Validator, to your project, Hibernate automatically triggers the validation before inserting and updating an entity. You can customize that and also trigger validation before removing an entity. I explained that in more details in my article.
You can use all features of the Bean Validation specification, including custom validation rules, to validate your entity attributes. I used that here to validate that the value of an entity attribute is within a defined range and here to check that only one out of 2 associations is set.
The example mapping that you posted in your question is a very good practice!
The #Column(nullable = false) part is not strictly necessary because the validation rule already ensures that the attribute can't be null.
Since Hibernate also have their own validation annotations, for example #NotBlank, I don't think it's a bad practice to use javax.validation.constraint here. As far as I know, Hibernate even tries to consider all of these annotations.
So for example a field annotated with #NotNull will not be nullable in the generated table (so adding nullable = false is redundant), a String field annotated with #Size(max=2047) will be a varchar(2047) in MySQL instead of the default varchar(255).
This can be useful to read: http://hibernate.org/validator/
The whole reference docs for the project: https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/#preface
EDIT: Based on Thorben Janssen's answer, the rest of my original answer below this can be discarded :)
I'm unsure if some more complicated constraints (for example a regular expression for phone numbers) are automatically enforced at the data layer or not. For example if you have a #Pattern for your phoneNumber field, that will work when your input is deserialized into your object. But if your setter methods dont have the same validation constraints, you might have an object in memory from some source with an incorrectly formatted phoneNumber that could be saved to the database. The safest way to use these constraints would probably include using programmatic validation with Validator.validate() before your database saves and updates.
Since Hibernate also have their own validation annotations, for example #NotBlank, I don't think it's a bad practice to use javax.validation.constraint here. As far as I know, Hibernate even tries to consider all of these annotations.
So, for example, a field annotated with #NotNull will not be nullable in the generated table (so adding nullable = false is redundant), a String field annotated with #Size(max=2047) will be a varchar(2047) in MySQL instead of the default varchar(255).

Is #JoinColumn annotation mandatory in Hibernate?

In Hibernate, to specify a column for joining association, #JoinColumn annotation in used, for example like this:
#ManyToOne
#JoinColumn(name="address_id")
public Address getAddress() {
return address;
}
In most cases, name of the column is snaked-cased class name plus _id. So it is reasonable to expect from Hibernate to derive it automatically (as it is done, for example, in Django's ORM). But is such behavior implemented somehow?
It is not necessary, JPA follows convention over configuration principle which means there are allways some default values that you can override with annotations.
In case of #JoinColumn, the default column name is generated like this: <field_name>_<id_column_name>
field_name is address in your case, and id_column_name is referring to the related entity's id, which is id. Thus, you get address_id by default.
It is not necessary to have #JoinColumn annotation. You can always override it. If you won't provide it in your code then Hibernate will automatically generate one for you i.e. default name for your column.

How to migrate a Hibernate NamingStrategy to (Implicit|Physical)NamingStrategy? Where is the documentation?

The NamingStrategy was already being marked as deprecated in Hibernate 4.2/4.3 (HHH-7079). Starting with Hibernate 5, now it will shipped with two replacements(?) interfaces ImplictNamingStrategy and PhysicalNamingStrategy (HHH-7078) and have finally ditched support for the old NamingStrategy. That's why Spring's upcoming Hibernate5 supported has even removed the configurer namingStrategy() and favor of implicitNamingStrategy() and physicalNamingStrategy(). So far, so good.
Although it is mentioned in some documents (i.e. in the incomplete working-5.0-migration-guide.md) and in (generated) release notes for the upcoming Hibernate 5 (as of today), I've found no concrete example how to use these actually.
Perhaps I've missed something, but neither the JavaDoc nor the issues shows any evidence of the idea both strategy types. Furthermore I've already one strategy based on NamingStrategy: a custom OracleNamingStrategy which is based on the well-known one.
While I'm interested in a proper solution in code (obviously), the actual issue is getting a working migration document and/or the conceptual idea of the restructured naming strategy.
Also related:
ImprovedNamingStrategy no longer working in Hibernate 5
Put below key value pair in your hibernate configuration file
hibernate.implicit_naming_strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl
hibernate.physical_naming_strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
If you are providing #Table and #Column annotation in your entity classes with names provided with an underscore i.e. user_id i.e. #Column(name="user_id"), it will take the column name as user_id; if you give it as userid then it will change to user_id if you use no strategy or implicit strategy (specifically spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl). So, if you want a strategy where the entity attribute name changes to one with underscore and lowercase letters i.e. something from userId to user_id, you should use implicit or no strategy (which actually uses implicit strategy).
If you don't want your naming strategy to add an underscore to the column name or class name, then the strategy that you need to use would look like:
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl. The things that you provide in annotations #Table and #Column’s name attribute would remain as it is.
If you don't want to provide annotations and want to manually handle the table name and column names, you should extend the class org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl and override the required methods. If you still use annotations for some of the cases here, remember the overridden methods will apply on the names written in those annotations.
spring.jpa.hibernate.naming.physical-strategy=example.CustomStrategy

What is the use of the #Access annoation in JPA means at the Entity level?

I saw this #javax.persistence.Access(javax.persistence.AccessType.FIELD) for a Entity.
What does this mean? Is it really required to declare #Access this for a entity.
No, it's not required, but can be useful. #Access is used to specify how JPA must access (get and set) mapped properties of the entity. If access type is set to FIELD, the values will directly be read/set on the field, bypassing getters and setters. If set to PROPERTY, the getters and setters are used to access the field value.
By default (at least with Hibernate), FIELD is used if the #Id annotation is on a field, and PROPERTY is used if the #Id annotation is on a getter.

Reference "to any" with JPA

is it possible to model a reference to "any" (entity) with JPA? Similar to a reference of type Object in Java, which can hold any object.
Thanks for your answer,
Dominik
You should think about representation of the reference in database.
If reference is represented by a single foreign key, then referenced column should be guaranteed to be unique for all possible referenced entities. In JPA it's possible only for entites in inheritance hierarchy, so you'll get a reference to the root of some inheretence hierarchy of entites instead of Object.
Reference may be represented by a pair of values <type of referenced entity, foreign key>. This case is not supported by plain JPA, but supported in Hibernate by Hibernate's own #Any annotation.
According to DataNucleus this is not possible (search in this for java.lang.Object):
http://www.datanucleus.org/products/accessplatform_1_1/jpa/types.html
For JDO we introduced our our Object-like abstract class called Subject which is annotated for persistence and extended all other persistable object from it. That works in JDO and I think it should work in JPA as well.

Categories

Resources