Map ArrayList with Hibernate - java

I just coded my first Hibernate examples.
The database connection works and I understand how I can map a String from a POJO to a database field:
private String firstName;
And in the mapping file:
<property name="firstName" type="java.lang.String">
<column name="FIRSTNAME" />
</property>
But how can I map an ArrayList to the database? A simpl example from the mapping xml file would be appreciated.
Cheers
UPDATE
I switched to List instead of ArrayList found an example. Now I map as follows:
<list name="test" inverse="false" table="CONTACT" lazy="true">
<key>
<column name="ID" />
</key>
<list-index></list-index>
<element type="java.lang.String">
<column name="TEST" />
</element>
</list>
Unfortunately, I get an exception that I do not understand:
Exception in thread "main" org.hibernate.MappingException: Foreign key (FK6382B0003257FF7F:CONTACT [ID])) must have same number of columns as the referenced primary key (CONTACT [ID,idx])
Any ideas?
Cheers

I notice that you are using XML to map your POJOs. You will find some information about that here.
for example:
<list name="myArrayListProperty" cascade="all">
<key column="parent_id"/>
<index column="idx"/>
<one-to-many class="WhatIsInTheList"/>
</list>
However, using annotations have some advantages. This link will explain how to map any collection using annotations.

See the collection mapping section of the docs. There are multiple ways to map a list (one-to-many, many-to-many, a collection of elements). You can map it as a list or as a bag, so read the whole section.

You have a little error in the XML configuration:
When you have a list the solution to map this list using a database is to link with a additional table, so instead of doing:
<list name="test" inverse="false" table="CONTACT" lazy="true">
<key>
<column name="ID" />
</key>
<list-index></list-index>
<element type="java.lang.String">
<column name="TEST" />
</element>
</list>
You should have to do map to a new data table that holds the list values:
<list name="test" inverse="false" table="CONTACT_test" lazy="true">
<key>
<column name="ID" />
</key>
<list-index></list-index>
<element type="java.lang.String">
<column name="TEST" />
</element>
</list>
Hibernate automatically creates the new table for you.

Related

Hibernate cascade=save-update, updates all siblings of new child entity

I have a parent-child configuration of hibernate as below
<class name="A" table="TAB_A">
<... columns defined here ...>
<map name="lookup" inverse="true" cascade="all-delete-orphan" lazy="false" fetch="join" access="field" >
<key column="A_FK" />
<map-key type="string" column="key_name" />
<one-to-many class="B" />
</class>
<class name="B" table="TAB_B>
<... columns defined here ...>
<many-to-one name="a" class="A" column="A_FK" not-null="true" cascade="save-update" />
<property name="key" column="key_name" type="string" not-null="true" />
</class>
Recently we upgraded hibernate from 2.x to 4.x.
The problem we are facing after this migration is that the new insert in table B inserts the new records as well as updates all the existing records of TAB_B.
The update statement updates the "key_name" column of TAB_B.
I tried looking into the source code of Hibernate and found that the AbstractCollectionPersister.insertRows method is now overridden in OneToManyPersister.insertRows. This overridden method calls another method writeIndex which invokes the update statements.
So is this intended behavior? If not why the child entries are getting updated?
Are we missing something?
Hanumant

Read an Excel file (saved in several blobs) sequentially into one InputStream

I need to process big Excel files. My problem is heap space especially with XLS format. Even if I have one Apsose LighCells API to parse it sequentially I need to retrieve the file from the database in chuncks.
So far I have the file in the database in chunks of 40kb. I have an Import table (storing general information related to the import, for instance start and end time, data type etc.) and an ImportData table (containing the chunks of data as blobs). I have a one to many relation between Import and ImportData:
<hibernate-mapping> <class name="com.company.import.pojos.Import
table="IMPORT_TABLE">
<id name="id" type="integer">
<column name="ID" />
<generator class="some.id.generator.IdGenerator"></generator>
</id>
<property name="startTime" type="timestamp">
<column name="START" />
</property>
<property name="endTime" type="timestamp">
<column name="END" />
</property>
<property lazy="false" name="datatzpe" type="com.company.import.enums.ImportDataType">
<column name="DATATYPE" />
</property>
<bag name="importDataList" table="IMPORT_DATA" lazy="true" cascade="all" inverse="false">
<key column="IMPORT_TABLE_ID"/>
<one-to-many class="com.company.import.pojos.ImportData"/>
</bag>
</class> </hibernate-mapping>
<hibernate-mapping> <class
name="com.company.import.pojos.ImportData" table="IMPORT_DATA">
<id name="id" type="integer">
<column name="ID" />
<generator class="some.id.generator.IdGenerator"></generator>
</id>
<property name="importTableID" type="integer">
<column name="IMPORT_TABLE_ID" />
</property>
<property name="data" type="binary">
<column name="DATA" />
</property>
<property name="order" type="integer">
<column name="ORDER" />
</property> </class> </hibernate-mapping>
I use Hibernate (4.2.3.Final), but even lazy loading in not an option because then I will have the whole list of ImportData objects in memory which is why I get an OutOfMemoryError and I want to avoid that.
Providing more memory is not an option (the application runs ona container that runs other applications as well, and several users might process files at the same time so the heaps space problem will eventually happen), therefore I am looking for a way to always read the next chunk of data and provide it to the stream that is given to the Aspose API.
I create my workbook in Aspose simply like this:
InputStream inStream = ....;// get the input stream somehow
Workbook workbook = new Workbook(inStream);
You may need to implement your own InputStream, which handles multiple IS as one, handling that when you reach the end of one IS you close it and pick the next one to fill the rest of the read buffer.
I do not know any implementation for this behaviour.
How big is your file ?

what type of mapping is this?

With the hibernate mapping file as shown :
<hibernate-mapping>
<class name="pojo.Ghazal" table="ghazal">
<id name="s_no">
<generator class="increment" />
</id>
<property name="poem" />
<property name="poet" />
<map name="map" table="linked">
<key column="s_no" />
<index column="key_" type="string" />
<element column="val_" type="string" />
</map>
</class>
</hibernate-mapping>
what type of mapping it is ?
The pojo named ghazal has the following properties :
s_no
poem
poet
map
I have heard many types of mapping like many to one, one to one, etc etc.
This is an association done with collection(Map named "map" in your case) of values, relationship is Many to many, you can find the detailed docs here

Hibernate java web application

I am working on a java JSP webapplication that uses the hibernate framework.
I am a total beginner with JSP/hibernate, and I can't seem to get hibernate to work.
I have followed this tutorial: https://netbeans.org/kb/docs/web/hibernate-webapp.html
It all worked. I used xampp with phpmyadmin, and I could execute HQL query's through the hibernate.cfg.xml file.
Then I was trying the same thing with the database I am using for the web application. Followed all steps and went through all the wizards. But I can't execute HQL query's.
the following error is given:
org.hibernate.MappingException: An association from the table campingsperfestival refers to an unmapped class: festivalOverview.Campings
at org.hibernate.cfg.Configuration.secondPassCompileForeignKeys(Configuration.java:1252)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1170)
at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:324)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1286)
at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:859)
I followed the Hibernate Mapping Files and POJOs from Database wizard, and it generated a .java and .hbm.xml file for all tables in the database except for one table: the 'campingsperfestival' table. I've done the wizard again a few times and started it all over but it still doesn't generate the .java and .hbm.xml file for the 'campingsperfestival' table.
The 'campingsperfestival' table is a table with 2 id's that both have a foreign key. There are festivals and campings that both have ID's, the 'campingsperfestival' matches those 2 id's in one table.
Campings.hbm.xml:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 20-apr-2013 12:04:37 by Hibernate Tools 3.2.1.GA -->
<hibernate-mapping>
<class name="festivalOverview.Campings" table="campings" catalog="groep11_festivals">
<id name="campId" type="java.lang.Integer">
<column name="camp_id" />
<generator class="identity" />
</id>
<property name="campAdres" type="string">
<column name="camp_adres" not-null="true" />
</property>
<property name="campCap" type="int">
<column name="camp_cap" not-null="true" />
</property>
<set name="festivalses" inverse="true" table="campingsperfestival">
<key>
<column name="camp_id" not-null="true" />
</key>
<many-to-many entity-name="festivalOverview.Festivals">
<column name="fest_id" not-null="true" />
</many-to-many>
</set>
<set name="facpercamps" inverse="true">
<key>
<column name="camp_id" not-null="true" />
</key>
<one-to-many class="festivalOverview.Facpercamp" />
</set>
</class>
</hibernate-mapping>
Festivals.hbm.xml:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 20-apr-2013 12:04:37 by Hibernate Tools 3.2.1.GA -->
<hibernate-mapping>
<class name="festivalOverview.Festivals" table="festivals" catalog="groep11_festivals">
<id name="festId" type="java.lang.Integer">
<column name="fest_id" />
<generator class="identity" />
</id>
<property name="festNaam" type="string">
<column name="fest_naam" length="100" not-null="true" />
</property>
<property name="festLocatie" type="string">
<column name="fest_locatie" length="200" not-null="true" />
</property>
<property name="festDatum" type="date">
<column name="fest_datum" length="10" not-null="true" />
</property>
<property name="festDuur" type="byte">
<column name="fest_duur" not-null="true" />
</property>
<set name="ticketses" inverse="true">
<key>
<column name="fest_id" not-null="true" />
</key>
<one-to-many class="festivalOverview.Tickets" />
</set>
<set name="bandsperfestivals" inverse="true">
<key>
<column name="fest_id" not-null="true" />
</key>
<one-to-many class="festivalOverview.Bandsperfestival" />
</set>
<set name="campingses" inverse="false" table="campingsperfestival">
<key>
<column name="fest_id" not-null="true" />
</key>
<many-to-many entity-name="festivalOverview.Campings">
<column name="camp_id" not-null="true" />
</many-to-many>
</set>
<set name="tickettypesperfestivals" inverse="true">
<key>
<column name="fest_id" not-null="true" />
</key>
<one-to-many class="festivalOverview.Tickettypesperfestival" />
</set>
</class>
</hibernate-mapping>
I'm only a beginner with hibernate and really don't know how to solve this problem. Any help is greatly appreciated!
I assume campingsperfestival is a join table between two classes, Campings and Festival? Have you defined both these classes and their mapping?
The error you have there is saying it can't create campingsperfestival because it is referring to Campings, which is not defined as as hibernate class. So make sure Campings is defined and you have the mapping correct.
If you are still unclear we may be able to help more if you show the java/mappings you have for campings and festival.
As an aside, if this is a new project you are embarking on, I would really recommend using annotation based hibernate classes. You may also find it a more productive learning experience to create your hibernate entity classes yourself rather than using netbeasns - but that's down to personal preference.

hibernate: how to create a composite foreign key in xml?

I have a class Event containing a composite primary key (start date and end date).
A EventPlanning class holds a Set of such Event objects and has to persist them using hibernate with XML.
I can do this for classes with a common primary key:
<!-- EventPlanning xml -->
....
<id name="id" column="id">
<generator class="native" />
</id>
<property name="name" column="name" type="string" update="false" />
<set name="events" table="events" cascade="all">
<key column="event_id"> // ###### here! ######
</key>
<one-to-many class="myPackage.Event" />
</set>
...
but I can't find out how this works with a composite key..
replacing the <key column="event_id"> with the following code doesn't work:
<key>
<property column="start_date" />
<property column="end_date" />
</key>
I'd be glad if somebody can show me the right syntax! :)
the Event xml looks like this:
<class name="myPackage.Even" table="events">
<composite-id>
<key-property name="startDate" column="start_date" type="date" />
<key-property name="endDate" column="end_date" type="date" />
</composite-id>
<property name="signinDeadline" column="signin_deadline"
type="date" />
<property name="confirmationDeadline" column="confirmation_deadline"
type="date" />
<set name="participants" table="participants" cascade="all">
<key column="event_id">
</key>
<one-to-many class="myPackage.Participants" />
</set>
</class>
thanks in advance! :)
Something like this works for me:
<class name="YourClass" table="your_table" ...>
<composite-id name="compositeId" class="DoubleDate">
<key-property name="start_date" column="start_date"/>
<key-property name="end_date" column="end_date"/>
</composite-id>
...
</class>
public class DoubleDate implements Serializable {
private Date start_date, end_date;
public DoubleDate() {
}
// setters, getters
}
public class YourClass {
private DoubleDate compositeId;
// public no args ctr, getters, setters, etc
}
After having now worked longer with JPA and Hibernate, I'd just say that you simply should not use composite primary keys. Caches use ids as keys that point to cached values, data retrieving methods like get and load expect the id as parameter etc.
The advantages gained by having an id field pay off against the additional space it needs.

Categories

Resources