How to generate column with length property using JPA tools? - java

I was generating Entity class for tables using JPA Tools in Eclipse Mars.It generate this
#Column(name="someColumn")
private String someColumn;
type of data member in Entity class which is of varying(130) type in databse. I have to manually edit every data member like this
#Column(name="someColumn",length=130)
private String someColumn;
by adding length in Column annotation. How to configure JPA Tools for generating data member with length automatically?

Related

Alter table from jpa annotations in Java

I have a definition for a column like that:
#Column
private String my_column;
And by default in Postgres database type for this field is character varying(255).
Now, I want to change the data type for this column.
How I can do this without entry in database and alter table?
I tried this:
#Lob
#Column
private String my_column;
And
#Column(columnDefinition = "TEXT")
private String my_column;
But, without results.
The thing is, that JPA does not handle Schema changes.
JPA maps your existing DB to Java Classes, it does not manage the database it self.
As for schema changes managment.
A common practice is to have a schema migration tool to handle that, for example Flyway and Liquibase are a popular solutions.
There you can write a SQL script, to change the DB column type to "text"
and it will apply those changes when you run the DB migration process.
Or you can always just access your DB and modify it manually.

redundant id values inserted despite using #inheritance

In a spring mvc app using hibernate, jpa, and MySQL, I have a BaseEntity that contains an id field that is unique across all classes that inherit from BaseEntity, using #Inheritance(strategy = InheritanceType.TABLE_PER_CLASS). Some data is imported into the MySQL database using an external dml.sql file run from the command line. The imported data is carefully planned so that all the ids that need to be managed as part of the BaseEntity inheritance group are unique within their inheritance group.
The problem is that hibernate is not taking the values of the ids already in the database into account when it inserts a new record into the database. Instead, hibernate is saving an id value in one of the descendent entities which is identical to an id stored in one of the other descendent entities.
How can I configure hibernate to respect the id values already in the database when it saves a new entity within the same inheritance group?
Some relevant facts are:
All of the objects in the MySQL database were created directly from the hibernate mappings in the app by using hbm2ddl.
I cannot use #MappedSuperClass for BaseEntity because BaseEntity is used as a property of one of the entities in the app, so that entities of various types can be stored in the same property of that entity. When I was using #MappedSuperClass, eclipse was giving compile errors saying that BaseEntity cannot be instantiated directly because it has #MappedSuperClass annotation.
Note: The file sharing site seems to be center-justifying all the code. You can fix this by simply cutting and pasting it into a text editor.
You can read the code for BaseEntity by clicking on this link.
The code for the entity whose id values are being set incorrectly by hibernate can be read by clicking on this link.
The jpql code for saving the entity whose id is being set incorrectly is as follows:
#Override
#Transactional
public void saveCCD(HL7ConsolidatedCareDocument ccd) {
if (ccd.getId() == null) {
this.em.persist(ccd);
this.em.flush();
}
else {
this.em.merge(ccd);
this.em.flush();
}
}
I have never done this using hibernate or mysql ut have done something similar with EclipseLink + PostgreSQL. So there might be some mistakes below.
With generation type TABLE you might want to explicitly specify some additional parameters using the TableGenerator annotation. That way you are certain where hibernate is storing things.
#Id
#GeneratedValue(
strategy=GenerationType.TABLE,
generator="TBL_GEN")
#javax.persistence.TableGenerator(
name="TBL_GEN",
table="GENERATOR_TABLE",
pkColumnName = "mykey",
valueColumnName = "hi"
pkColumnValue="BaseEntity_Id",
allocationSize=20
)
What you need to do when you bypass hibernate is to reserve the ids you need by updating the row with mykey BaseEntity_Id in the table GENERATOR_TABLE.
For details on the annotations see paragraph 5.1.2.2

Eclipselink and ArrayMapping JPA problem

I have problem extracting data of the Oracle custom type from the database.
One of the columns in the table is of the Oracle custom type (which is actually VARRAY):
Here is create statement for this type:
create or replace TYPE CAlarmMessList AS VARRAY(15) OF CAlarmMess;
Where CAlarmMess is the following:
create or replace TYPE CAlarmMess AS OBJECT (EreignisTypId NUMBER(9), EreignisKlasseId NUMBER(9), AlarmZeit DATE, ParamWert1 VARCHAR2(65 CHAR), ParamWert2 VARCHAR2(65 CHAR), ParamWert3 VARCHAR2(65 CHAR) [....]
And the field I need has name ALARME and type CALARMMESSLIST.
I generated Entity for the table (WSENSORSTATE) using Oracle tools for Eclipse. This field was generated as Object field.
I manually created java type CAlarmMess with fields:
private BigDecimal ereignisTypId;
private BigDecimal ereignisKlasseId;
private Date alarmZeit;
private String paramWert1;
private String paramWert2;
private String paramWert3;
And changed type of the field in my Entity to List of CAlarmMess.
When I added customizer for my entity:
#Customizer(com.companyname.entities.WsensorstateCustomizer.class)
Where customize method is the following:
public void customize(ClassDescriptor descriptor) throws Exception {
ObjectArrayMapping arrayMapping = new ObjectArrayMapping();
arrayMapping.setReferenceClass(Wsensorstate.class);
arrayMapping.setAttributeName("alarme");
arrayMapping.setFieldName("CAlarmMess");
arrayMapping.setStructureName("CAlarmMessList");
descriptor.addMapping(arrayMapping);
}
Now it falls with following error:
Exception [EclipseLink-197] (Eclipse Persistence Services - 2.0.1.v20100213-r6600): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: The mapping [alarme] is not the appropriate type for this descriptor
Mapping: org.eclipse.persistence.mappings.structures.ObjectArrayMapping[alarme]
Descriptor: RelationalDescriptor(com.companyname.entities.Wsensorstate --> [DatabaseTable(WSENSORSTATE)])
I tried to add #StructConverter for the CAlarmMess but it also didn't work.
All suggestion will be appreciated, I already spent too much time working on it. :)
You have a WsensorstateCustomizer customizer I assume set on the Wsensorstate entity, but the mapping you are adding is set to reference Wsensorstate.class. This is telling EclipseLink that you are trying to build an array/collection of Wsensorstate, which isn't allowed as Wsensorstate is an entity with a RelationalDescriptor. Instead, you will have to create a java class for the CAlarmMess structure so that you get a collection of CAlarmMess objects in your Wsensorstate entity. Or you can map the alarme directly to a VARRAY and deal with the Oracle object yourself, but I'd go with the previous approach.
You will need to build an ObjectRelationalDataTypeDescriptor for the CAlarmMess java class as I do not know if this is exposed through the JPA interface, much like you are building the ObjectArrayMapping. A simple example from the EclipseLink automated tests is:
ObjectRelationalDataTypeDescriptor descriptor = new ObjectRelationalDataTypeDescriptor();
// SECTION: DESCRIPTOR
descriptor.setJavaClass(Phone.class);
Vector vector = new Vector();
vector.addElement("PolicyHolders");
descriptor.setTableNames(vector);
// SECTION: PROPERTIES
descriptor.descriptorIsAggregate();
descriptor.setStructureName("PHONE_TYPE");
descriptor.addFieldOrdering("PHONETYPE");
descriptor.addFieldOrdering("AREACODE");
descriptor.addFieldOrdering("PHONENUMBER");
descriptor.addDirectMapping("type", "getType", "setType", "PHONETYPE");
descriptor.addDirectMapping("areaCode", "getAreaCode", "setAreaCode", "AREACODE");
descriptor.addDirectMapping("number", "getNumber", "setNumber", "PHONENUMBER");
Which will need to be added to the session in a session customizer before it can be used by the ObjectArrayMapping.

How to bind uuid field with spring mvc and hibernate

I have entity class which is annotated with hibernate and MySQL. I want to generate a UUID and insert it in the user table.
How can I map that field with hibernate?
How to bind that field with spring mvc and jsp because that
field will be autogenerated and won't be in the user form?
It's been a while since I wrote any Hibernate but I'm fairly sure you can just initialise it on construction and the id will be written to the DB on save and loaded from the db on load. You may find that a random UUID is less performant than the standard long primary key.
class MyEntity {
#Id
private String id = UUID.randomUUID().toString();
Well, you shouldn't bind any fields in your Form object that the user isn't actually filling out in the HTML form. Just let the DAO and backend classes deal with populating any sort of auto-generated ID.
As for generating a UUID with Hibernate, you can use Hibernate's built-in uuid generator or one of several other built-in generators, or you can use whatever type of unique ID generation logic is built into your Database Engine and just mark the ID field with <generator class="select"/> to have Hibernate query the database after inserting the row to find out the database-generated ID.

Hibernate #Index error on long string columns

I have a data model where I need a String column to be indexed by the backing database:
#Entity
public class A {
// ...
#Column(length=2048)
#Index(name="strFieldIndex")
private String strField;
}
When adding the length attribute of #Column(length=2048) (for which hibernate doesn't generate varchar anymore) the following error message appears on MySQL:
ERROR org.hibernate.tool.hbm2ddl.SchemaExport -
BLOB/TEXT column 'strField' used in key specification without a key length
I've scanned the API docs for hibernate and I can't find an approach to setting the key length.
I think you have to declare this index manually as required for MySQL, since Hibernate can't handle all DBMS-specific requirements. For example, using <database-object> syntax.

Categories

Resources