Hibernate session.get() Problem with UUID string ID - java

I am having a problem with Hibernate.
The primary key of ID in mysql table is UUID style String. e.g.08fe2a75-5d40-4645-896d-aab2a3ac96b8
But I can not use session.get() to fetch out the data for some reason.
Software software=(Software)session.get(Software.class, id);
It seems ok with integer IDs.
Please advise

Activate the logging of the generated SQL to see what is happening exactly. This can be done by setting the following property in your Hibernate configuration:
<property name="hibernate.show_sql" value="true"/>
Or set the following category to debug in the configuration of your logging backend.
org.hibernate.SQL
Compare the generated query with the expected result (that works in your SQL client).
Reference
Hibernate Core reference guide
Section 3.5. "Logging"

Related

How to stop persistence from altering database, JPA

I am using camel and open jpa as persistent provider, but I don't want alter statements to be run on prduction.
Snapshot of persistence.xml
<persistence-unit name="camel-openjpa-oracle-alert" transaction-type="RESOURCE_LOCAL">
.
.
<provider>
org.apache.openjpa.persistence.PersistenceProviderImpl
</provider>
<properties>
<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=false)" />
</properties>
.
.
</persistence-unit>
What value we have to put for openjpa.jdbc.SynchronizeMappings, so that alter command are not executed.
I searched but was unable to find any such value.
It would be nice to know a little more about what you are doing and why you need to use SynchronizeMappings. The fact that you use ForeignKeys=true tells me you want OpenJPA to read you schema and determine if you have any database FKs defined (i.e. so OpenJPA knows about these FKs so it can order SQL properly to honor parent/child FK constraints). This is a perfectly valid use of SynchMappings. However, by using 'buildSchema', you are specifically telling OpenJPA to make "the database schema match your existing mappings"....this comment is lifted from this OpenJPA doc:
http://openjpa.apache.org/builds/1.2.3/apache-openjpa/docs/ref_guide_mapping.html#ref_guide_mapping_synch
Therefore, you are specifically telling OpenJPA to update your database schema. You can remove the 'buildSchema' if you don't want OpenJPA to update your schema to match your domain model. That is, try:
Or you could use 'validate' in place of 'buildSchema'....however, as the above doc states, OpenJPA will throw an exception if it finds a schema/domain mismatch which may not be what you want. I suggest you read the above doc, and look at the available options to you.
Thanks,
Heath Thomann

JPA: globally changing type of the database column generated in schema

We are generating our database schema using JPA, using this property set in persistence.xml:
<property name="hibernate.hbm2ddl.auto" value="update" />
But it turned out that varchar column type generated by JPA for our String properties is too short. I know we can add:
#Column(columnDefinition = "varchar(2000)")
String someStr;
For every String property of our entities but it would be a lot of work.
It would be much better to globally configure JPA in the way that it generates varchar(2000) for every String in our entities. Is this possible?
PS. We use Hibernate as JPA backend if this fact matters.

Merge an entity, change its id, merge again, cause "mapped to a primary key column in the database. Updates are not allowed" error

I have a JPA program where EclipseLink is the Persistence provider. When I merge an user entity, change its ID, and try to merge the same user instance again, an error is thrown. I rewrite my code to illustrate my problem in the simplest way.
User user = userManager.find(1);
userManager.merge(user);
System.out.println("User is managed? "+userManager.contains(user);
user.setId(2);
userManager.merge(user);
The above code is not in a transaction context. userManager is a stateless session bean with an EntityManager injected. When executed, the console prints:
User is managed? false
Exception [EclipseLink-7251] (Eclipse Persistence Services - 2.1.3.v20110304-r9073): org.eclipse.persistence.exceptions.ValidationException
Exception Description: The attribute [id] of class [demo.model.User] is mapped to a primary key column in the database. Updates are not allowed.
The exception occurs at the second merge() invocation.
If I create a new user, sets its ID and merge it, it works:
User user = userManager.find(1);
userManager.merge(user);
System.out.println("User is managed? "+userManager.contains(user);
User newUser = new User();
newUser.setId(2);
userManager.merge(newUser);
So what is the difference between the first scenario and second one? According to the JPA specification, as long as the entity is in detached state, the merge should succeed, right?
(Assuming the entity with ID=2 exists)
Why the EclipseLink provider seems to be bothered by the fact that the user entity has been merged before?
Update: It seems to be an bug of EclipseLink. I have replaced the persistence provider from EclipseLink to Hibernate:
I change
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
to
<provider>org.hibernate.ejb.HibernatePersistence</provider>
No error has been thrown.
The reason is that the Id may be inserted/defined - as you do in your second example, but not changed/updated - as you try in your first example. The JPA provider tries to reflect the change in the database and fails.
JPA 2 spec ยง2.4 says
The application must not change the value of the primary key. The
behavior is undefined if this occurs.
It seems to be an bug of EclipseLink. I have changed the persistence provider from EclipseLink to Hibernate:
from
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
to
<provider>org.hibernate.ejb.HibernatePersistence</provider>
No error has been thrown.
The version of EclipseLink is 2.3.2. (which is shipped with the latest Glassfish application server 3.1.2).
The version of hibernate is, as of now the latest, 4.1.7.
Try <property name="eclipselink.weaving.internal" value="false"/> in persistence.xml as per
http://blogs.nologin.es/rickyepoderi/index.php?/archives/95-Weaving-Problem-in-EclipseLink.html
This answer is 4 years late but anyway.
You can update it by executing regular update queries using SQL or JPQL or Criteria API. I find the last one is the best.
Here is a code example that can do the trick. I have tried it in a similar situation and it works fine with EclipseLink.
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaUpdate<User> cu = cb.createCriteriaUpdate(User.class);
Root<User> c = cu.from(User.class);
cu.set(User_.id, newId).where( cb.equal(c.get(User_.id), oldId) );
em.createQuery(cu).executeUpdate();
Instead of User_.id you can pass the name of the field as a String e.g. "id".
Another example http://www.thoughts-on-java.org/criteria-updatedelete-easy-way-to/

Add column in a table mapped using hibernate, without losing existing data

I have a table called Person which I have already mapped in hibernate I has already some data which I do not want to loose. I need to add new column called address, Any idea how to do that in hibernate ?
Thanks in Advance..
If you current tables are generated by Hibernate , you can simply add the address property in the java entity class for the address column . Then set the hibernate.hbm2ddl.auto property to update and hibernate will automatically create this column when the SessionFactory is built next time . Hibernate will not change any data store in your database when hibernate.hbm2ddl.auto is update.
Or , you can manually issue the SQL to alter the table structure and then add the address property in the java entity class for the address column.
Likely you are not forced to use Hibernate to create/update database schema. I assume you have something like this in your configuration:
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
Just change value to "validate", perform changes to the mappings and execute ALTER TABLE statements separately.
Other option is to use "update" to let Hibernate figure out how to update your table structure. I suggest to keep it in your hands and just execute DDL SQL manually.
You should also read this other SO question/answer: Hibernate: hbm2ddl.auto=update in production? before you set hibernate.hbm2ddl.auto to update.

JPA and toplink create-table on if they don't already exist?

Looks like jpa is something which makes me ask a lot of questions.
Having added this
<property name="toplink.ddl-generation" value="create-tables"/>
my JPA application always creates tables when running, which results in exceptions in case the tables already exist. I would like JPA to check if the tables already exist and if not create them, however I could not find a value for the property above which does this.
So if I just turn it off, is there a way to tell JPA manually at some point to create all the tables?
Update here's the exception I get
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'tags' already exists
Error Code: 1050
Call: CREATE TABLE tags (ID BIGINT AUTO_INCREMENT NOT NULL, NAME VARCHAR(255), OCCURRENCE INTEGER, PRIMARY KEY (ID))
MySQLSyntaxErrorException?! Now that's wrong for sure
According to http://www.oracle.com/technology/products/ias/toplink/JPA/essentials/toplink-jpa-extensions.html#Java2DBSchemaGen toplink does not have an option to update exiting tables, I'm not sure if I would trust it to do the right thing anyway.
You could configure toplink to generate a sql script that you then would have to execute manually to create all tables. The filenames and location can be configured like this:
<property name="toplink.ddl-generation" value="create-tables"/>
<property name="toplink.ddl-generation.output-mode" value="sql-script"/>
<property name="toplink.create-ddl-jdbc-file-name" value="createDDL.sql"/>
<property name="toplink.drop-ddl-jdbc-file-name" value="dropDDL.sql"/>
<property name="toplink.application-location" value="/tmp"/>
I would like [my] JPA [provider] to check if the tables already exist and if not create them, however I could not find a value for the property above which does this.
Weird, according to the TopLink Essentials documentation about the toplink.ddl-generation extension, create-table should leave existing table unchanged:
TopLink JPA Extensions for Schema Generation
Specify what Data Descriptor Language
(DDL) generation action you want for
your JPA entities. To specify the DDL
generation target, see
toplink.ddl-generation.output-mode.
Valid values: oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider
none - do not generate DDL; no
schema is generated.
create-tables - create DDL for
non-existent tables; leave existing
tables unchanged (see also
toplink.create-ddl-jdbc-file-name).
drop-and-create-tables - create DDL for all tables; drop all existing
tables (see also
toplink.create-ddl-jdbc-file-name
and
toplink.drop-ddl-jdbc-file-name).
If you are using persistence outside
the EJB container and would like to
create the DDL files without creating
tables, additionally define a Java
system property INTERACT_WITH_DB and
set its value to false.
Liquibase (http://www.liquibase.org) is good at this. It takes some time to get fully used to it, but I think it's worth the effort.
The Liquibase-way is independent of which JPA persistence provider you use. Actually, it's even database agnostic.

Categories