Writing comments for an entity bean property in hibernate - java

Is it possible to write comments for every property of an Entity bean in Hibernate, such that when i generate the table using ddl, it creates the tables with column comments?

I think you have to use the columnDefinition property of the #Column annotation. See http://docs.redhat.com/docs/en-US/JBoss_Enterprise_Web_Server/1.0/html-single/Hibernate_Annotations_Reference_Guide/index.html
or EJB3 reference (ejb-3_0-fr-spec-persistence.pdf -- page 167):
http://download.oracle.com/otndocs/jcp/ejb-3_0-fr-eval-oth-JSpec/

Related

Where to set hibernate.id.new_generator_mappings property?

I've wasted too much time on this ...
I'm using oracle and I have a sequence (MY_TABLE_SEQ) defined which increments by 1.
In my Pojo I have:
#SequenceGenerator(name = "MY_SEQ", sequenceName="MY_TABLE_SEQ", allocationSize=50)
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="MY_SEQ")
This gives me a unique constraint issue. From my understanding I need to set the following property:
hibernate.id.new_generator_mappings=true
I've tried setting in my hibernate.cfg.xml file but it does not seem to make any difference. I've come across server post to place in persistance.xml but this is a standalone app, no webcontainer.
Setting allocationSize=1 works but of course it hits the db on each insert to get the next sequence. Setting the above property is suppose to resolve it.
I haven't tried Oracle, but I had similar issues to yours inserting into an AS400 DB2 table.
I had to remove the identity flag on the id column on DB2 table - and instead used a custom jpa/hibernate sequence generator. This is set up on the pojo/entity annotation of the #ID entity field as you've done.
DB2 had been giving me errors about missing SYSIBM.SYSSEQUENCES table, so evidently hibernate (version 5.2), doesn't recognize the native DB2 identity designation. A custom sequence was and effective workaround.
On the #ID entity field:
#GeneratedValue(generator = "table", strategy=GenerationType.TABLE)
#TableGenerator(name = "table", allocationSize = 20)
This example allocates a pool of 20 sequence numbers each time it queries the table.
Next, create the required table Hibernate needs with columns that match the hibernate5 API - must be in lower case ... so put quotes around the names to work around the auto-upper casing that DB2 defaults to. The API will error out if these names are in caps.
Table:
"hibernate_sequences"
example of 2 Columns used:
"sequence_next_hi_value" (integer, not nullable, 0 default)
"sequence_name" (character, sample length 20, not nullable, natural default)
In the configuration code for the dialect used - ex: Spring Boot programmatically, add these properties:
properties.put("hibernate.supportsSequences","false");
properties.put("hibernate.id.new_generator_mappings","false");
and in the *.properties file:
spring.jpa.properties.hibernate.dialect.supportsSequences=false
spring.jpa.properties.hibernate.id.new_generator_mappings=false
Database systems are case-sensitive for schema/table/field names. Also watch for typos everywhere, incl. property names.
Be sure your pojo/entity only contains private fields that will be mapped to the table. Static finals such as serialVersionUID are ok.
I will be doing someething similar for SQL Server soon.
For MySQL, I had no issues using an identity column as defined in a table ID field to insert records, so didn't have to make all these changes. A simpler setup since hibernate recognizes the identity designation in MySQL.
#GeneratedValue(strategy=GenerationType.IDENTITY)
was all that was needed in the pojo.
I'm a newbie at all this, so always looking for better ways ... but this worked for now.
I set the property like this in the hibernate.cfg.xml file and it works !
<property name="hibernate.jpa.compliance.global_id_generators" value="true"/>

How to mapping a list of java.net.URL with JPA?

I try:
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
protected List<URL> urlList;
But I get error:
org.springframework.beans.factory.BeanCreationException: Error creating
bean with name 'entityManagerFactory' defined in ServletContext resource
[/WEB-INF/servlet-context.xml]: Invocation of init method failed; nested
exception is org.hibernate.AnnotationException: Use of #OneToMany or
#ManyToMany targeting an unmapped class:
my.package.MyModel.urlList[java.net.URL]
I saw this answers, but I can't mapping list of URLs.
Using an ElementCollection and CollectionTable is the way to map a Collection of NON-ENTITY elements.
#ElementCollection
#CollectionTable(name="MY_URLS")
Collection<URL> urlList;
Then it would depend on whether your JPA provider supports persistence of that element type (URL) out of the box. My provider (DataNucleus) does. You always can use AttributeConverter if it doesn't
What version of Hibernate are you using? Also, in your database, what is the datatype of the column; is it varchar, or something else?
From what I am understanding, it looks like your issue is that Hibernate does not know how to translate the column in the database to the java.net.URL class, a Hibernate type would need to be defined to tell Hibernate how to handle this conversion.
It looks like Hibernate does have a built-in type that should handle this conversion, assuming you are using a version of Hibernate that has it -- 3.6 or greater, I think.
Try adding this annotation to your List:
#Type(type="org.hibernate.type.UrlType")
If your version of Hibernate does not have org.hibernate.type.UrlType or if your database column data type is not a varchar, you will need to create a custom Hibernate type that defines what Hibernate needs to do to convert whatever data type in the database to a java.net.URL and back. Let us know if it gets to that point and we can give you more information.

Hibernate handling of nullable=true in #Column

I am using Hibernate with Springs backed by a Mysql db.
Here is the entity similar to the one i use to make an entry
#Entity
#Table(name = "my_table") {
#Basic
#Column(name = "my_string", nullable = false)
private String myString;
}
The sql definition is
CREATE TABLE `my_table` (
`my_string` varchar(200) DEFAULT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Though the table allows null values, the column myString is non-nullable as per the JPA annotation. This is leading to unpredictable behaviour.
Q: Is the non-nullable ALWAYS enforced at the entity level while making inserts? Or is there some case in which it may be ignored
My expectation was that all of the entries should have been rejected. But with this setup, many entries (>7000) have gone into the table.
Only sometimes i get a DataIntegrityViolation exception from spring
org.springframework.dao.DataIntegrityViolationException: not-null property references a null or transient value: ...; nested exception is org.hibernate.PropertyValueException: not-null property references a null or transient value: ....
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:652)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:104)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:403)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:58)
....
....
Caused by: org.hibernate.PropertyValueException: not-null property references a null or transient value: ....
at org.hibernate.engine.internal.Nullability.checkNullability(Nullability.java:103)
....
I understand that having separate signature in the entity and the table is a bad practice, But i'm trying to identify what causes this behaviour and any other loopholes that might have been left out due to it.
Versions -
Mysql- 5.5
Hibernate - 4.0.0
Hibernate-jpa - 2.0
Spring-core- 3.1.0
Spring-jdbc- 3.1.2
People frequently confuse the #Column(nullable) and #NotNull annotations.
The #Column(nullable) is meant for the generated DDL scripts. But you don't use Hibernate to generate your DDL, so you shouldn't rely on it at all. What you want is #NotNull which is a runtime validation trigger.
If you define the Hibernate Validator Annotation (or JPA 2.0 ones) you can get the DDL for those as well:
Out of the box, Hibernate (as of version 3.5.x) will translate the
constraints you have defined for your entities into mapping metadata.
For example, if a property of your entity is annotated #NotNull, its
columns will be declared as not null in the DDL schema generated by
Hibernate.
And make sure you enable validation if you're using JPA with Hibernate.
If you are using JPA 2 and Hibernate Validator is in the classpath the
JPA2 specification requires that Bean Validation gets enabled. The
properties javax.persistence.validation.group.pre-persist,
javax.persistence.validation.group.pre-update and
javax.persistence.validation.group.pre-remove as described in Section
10.1.2, “Hibernate event-based validation” can in this case be configured in persistence.xml. persistence.xml also defines a node
validation-mode which can be set to AUTO, CALLBACK, NONE. The default
is AUTO.

Confusion: #NotNull vs. #Column(nullable = false) with JPA and Hibernate

When they appear on a field/getter of an #Entity, what is the difference between them? (I persist the Entity through Hibernate).
What framework and/or specification each one of them belongs to?
#NotNull is located within javax.validation.constraints. In the javax.validation.constraints.NotNull javadoc it says
The annotated element must not be null
but it does not speak of the element's representation in the database, so why would I add the constraint nullable=false to the column?
#NotNull is a JSR 303 Bean Validation annotation. It has nothing to do with database constraints itself. As Hibernate is the reference implementation of JSR 303, however, it intelligently picks up on these constraints and translates them into database constraints for you, so you get two for the price of one. #Column(nullable = false) is the JPA way of declaring a column to be not-null. I.e. the former is intended for validation and the latter for indicating database schema details. You're just getting some extra (and welcome!) help from Hibernate on the validation annotations.
The most recent versions of hibernate JPA provider applies the bean validation constraints (JSR 303) like #NotNull to DDL by default (thanks to hibernate.validator.apply_to_ddl property defaults to true). But there is no guarantee that other JPA providers do or even have the ability to do that.
You should use bean validation annotations like #NotNull to ensure, that bean properties are set to a none-null value, when validating java beans in the JVM (this has nothing to do with database constraints, but in most situations should correspond to them).
You should additionally use the JPA annotation like #Column(nullable = false) to give the jpa provider hints to generate the right DDL for creating table columns with the database constraints you want. If you can or want to rely on a JPA provider like Hibernate, which applies the bean validation constraints to DDL by default, then you can omit them.
The JPA #Column Annotation
The nullable attribute of the #Column annotation has two purposes:
it's used by the schema generation tool
it's used by Hibernate during flushing the Persistence Context
Schema Generation Tool
The HBM2DDL schema generation tool translates the #Column(nullable = false) entity attribute to a NOT NULL constraint for the associated table column when generating the CREATE TABLE statement.
As I explained in the Hibernate User Guide, it's better to use a tool like Flyway instead of relying on the HBM2DDL mechanism for generating the database schema.
Persistence Context Flush
When flushing the Persistence Context, Hibernate ORM also uses the #Column(nullable = false) entity attribute:
new Nullability( session ).checkNullability( values, persister, true );
If the validation fails, Hibernate will throw a PropertyValueException, and prevents the INSERT or UPDATE statement to be executed needesly:
if ( !nullability[i] && value == null ) {
//check basic level one nullablilty
throw new PropertyValueException(
"not-null property references a null or transient value",
persister.getEntityName(),
persister.getPropertyNames()[i]
);
}
The Bean Validation #NotNull Annotation
The #NotNull annotation is defined by Bean Validation and, just like Hibernate ORM is the most popular JPA implementation, the most popular Bean Validation implementation is the Hibernate Validator framework.
When using Hibernate Validator along with Hibernate ORM, Hibernate Validator will throw a ConstraintViolation when validating the entity.
Interesting to note, all sources emphasize that #Column(nullable=false) is used only for DDL generation.
However, even if there is no #NotNull annotation, and hibernate.check_nullability option is set to true, Hibernate will perform validation of entities to be persisted.
It will throw PropertyValueException saying that "not-null property references a null or transient value", if nullable=false attributes do not have values, even if such restrictions are not implemented in the database layer.
More information about hibernate.check_nullability option is available here: http://docs.jboss.org/hibernate/orm/5.0/userguide/html_single/Hibernate_User_Guide.html#configurations-mapping.

Why Hibernates ignores the name attribute of the #Column annotation?

Using Hibernate 3.3.1 and Hibernate Annotations 3.4, the database is DB2/400 V6R1, running that on WebSphere 7.0.0.9
I have the following class
#Entity
public class Ciinvhd implements Serializable {
#Id
private String ihinse;
#Id
#Column(name="IHINV#")
private BigDecimal ihinv;
....
}
For reasons I can't figure, Hibernate ignores the specified column name and uses 'ihinv' to generate the SQL:
select
ciinvhd0_.ihinse as ihinse13_,
ciinvhd0_.ihinv as ihinv13_,
...
Which of course gives me the following error:
Column IHINV not in table CIINVHD
Edit: I switched the log level of hibernate to DEBUG, and I see that it does not process the column annotation for that field. Tried several random things it just doesn't work.
Did anyone had this problem before? I have other entities that are very alike in the way that they are using # in their database field names and that are part of the PK and I don't have this problem with them.
You could try some kind of quoting:
For example:
#Column(name="`IHINV#`")
or
#Column(name="'IHINV#'")
Another option would be to dig in to source code Hibernate dialect for DB2 and see if it contains anything helpful.
Of course, the easiest way would be to remove the hash from column name if possible.
I suspect that the problem is the hash in the column name. A similar question on the hibernate forums suggests that backticks can be useful here.

Categories

Resources