Please help me with this hibernate problem, I'm new to hibernate and still trying to get my head around it. I can't seem to work this issue out. I imagine I'm missing something pretty simple.
I've followed the example here to achieve a many-to-one mapping, as my requirements are almost identical: http://www.coderanch.com/t/217519/ORM/java/Hibernate-Newbie-Many-Relation-Tutorial
Please note that when I try to persist the Picture object, the user variable is (at that point in time) empty, as is every other variable bar image.
Also note that I've set hibernate to generate the database schema by itself via config in the hibernate config file.
Here are my mapping files (declarations removed)
User.hbm.xml
<class name="msc.model.User" table="USER">
<id name="id" column="USER_ID">
<generator class="native"/>
</id>
<property name="username"/>
<property name="email"/>
<bag name="pictures"
table="PICTURE"
lazy="true"
cascade="save-update">
<key column="PICTURE_ID"/>
<one-to-many class="msc.model.Picture" />
</bag>
</class>
And Picture.hbm.xml
<class name="msc.model.Picture" table="PICTURE">
<id name="id" column="PICTURE_ID">
<generator class="native"/>
</id>
<property name="story"/>
<property name="tattooist"/>
<property name="pic"/>
<many-to-one name="user"
class="msc.model.User"
column="USER" />
<property name="image" type="blob">
<column name="IMAGE" not-null="true" />
</property>
</class>
The class files (getters and setters stripped)
Picture.java
package msc.model;
import java.io.File;
import java.sql.Blob;
public class Picture {
private Long id = null;
private User user = null;
private File pic = null;
private String story = null;
private String tattooist = null;
private Blob image = null;
}
User.java
package msc.model;
import java.util.ArrayList;
import java.util.List;
public class User {
private Long id = null;
private String username = null;
private String email = null;
private List<Picture> pictures = null;
}
The persistence code (note that bFile is byte stream created from a file):
Session hib_ses = HibernateUtil.getSessionFactory().getCurrentSession();
hib_ses.beginTransaction();
Picture picture = new Picture();
picture.setImage(Hibernate.createBlob(bFile));
Long id = (Long) hib_ses.save(picture);
hib_ses.getTransaction().commit();
Here is the exception:
Cannot add or update a child row: a foreign key constraint fails (`msc`.`picture`, CONSTRAINT `FK85BE8DE2885129D` FOREIGN KEY (`PICTURE_ID`) REFERENCES `user` (`USER_ID`))
Please help!
There is something very strange going on if that is the real error you get.
Cannot add or update a child row: a foreign key constraint fails (`msc`.`picture`, CONSTRAINT `FK85BE8DE2885129D` FOREIGN KEY (`PICTURE_ID`) REFERENCES `user` (`USER_ID`))
This says that PICTURE.PICTURE_ID is a reference to USER.USER_ID. But PICTURE_ID is the PK of picture, which Hibernate will generate upon insertion. Did you mean to create a constraint from PICTURE.USER to USER.USER_ID?
Oh, I see you wrote you generate the schema via Hibernate. I think the error is in your "bag" definition. The key column should not be PICTURE_ID, but USER.
It looks like you are trying to save the Picture before saving the User. Try saving the User first.
[edit]
From the mapping - it looks like there is a Parent/Child relationship between User and Picture.
There is a good example in the Hibernate Documentation for a Parent Child relationship.
If you want the User to be able to be null, then a uni-directional relationship would be better.
[edit]
Another good reference about mapping collections with Hibernate.
Related
I have an EMF containment hierarchy: An House contains a list of Rooms, represented using an ecore file.
Before persisting, when I initially create my house and populate it with rooms, the eContainer value for a Room object correctly show the containing house. I then use Hibernate (no Teneo involved) to save the house (which cascade-saves the rooms).
When I reload the House object, I get references to all the Rooms. However, the eContainer value for a Room is now null. This is relevant because I use EcoreUtil.delete(bathroom) to delete a Room from its containing house, and that uses EObject.eContainer().
Relevant Hibernate Mapping:
<class name="House" table="house" lazy="false">
<bag name="rooms" lazy="true" cascade="save-update, delete">
<key update="true">
<column name="house_id" unique="false"/>
</key>
<one-to-many class="Room"/>
</bag>
</class>
<class name="Room" table="room" lazy="false">
</class>
What should I do to delete EMF objects? Should I call something other than EcoreUtil.delete(obj)? Should I manually add the eContainer references on load? Should I change my hibernate mapping?
Hibernate requires every property to have a getter and setter. In EMF (not using Teneo at least), there is a getter for Rooms but no setter.
public EList<Room> getRooms() {
if (rooms == null) {
rooms = new EObjectContainmentEList<Room>(Room.class, this, housePackage.HOUSE__ROOM);
}
return rooms;
}
I provided my own setter below.
public void setRooms(List<Room> roomList) {
this.rooms = new BasicEList<>();
this.rooms.addAll(roomList);
}
This was incorrect because a BasicEList does not do any provide EMF notification, so the eContainer was not getting set. I changed to the following, which in the underlying implementation uses a EObjectContainmentEList and so far it seems to work.
public void setRooms(List<Room> roomList) {
ECollections.setEList(getRooms(), roomList);
}
I have a java object set to update. I used SaveOrUpdate method to do that.it works fine for updating children, but there is an issue with my requirement.
because I need to delete a child from database if one child is deleted.
please anyone have an good idea to implement this ?
Ex :-
project has a one to many relationship with people.
project has a atribute like,
class Project {
long id;
Set<People> people;
......
}
public void updateProject(Project project) {
try {
getCurrentSession().saveOrUpdate(project);
} catch (Exception ex) {
logger.error(ex);
}
project object contains people set but deleted some people Ids from that.
I need to update project with deleting unwanted people Ids
Thank you
I assume you have enabled cascading on your Project entity so my guess is that you need to add the orphanRemoval attribute to the relation.
Example for your case would be:
#OneToMany(cascade={CascadeType.ALL}, orphanRemoval=true)
Ref Code: Configure cascade with 'all-delete-orphan' for removing orphan data...
<hibernate-mapping>
<class name="User" table="UTABLE" >
<id name="UID" column="UID"/>
<property name="Name" column="F_Name"/>
<set name="phones" table="PHONE_NUMBERS" cascade="all-delete-orphan" lazy="true">
<key column="UID"/>
<one-to-many class="PhoneNumber" />
</set>
</class>
</hibernate-mapping>
My java application is using hibernate with Oracle 10g as the database.
I have landed into an issue and not able to proceed and i need your help here.
Below is the issue that i am facing.
I have a Column in one of my Oracle table which has a datatype of Varchar2(1 byte).
I want to know the proper dataype that i need to use in my pojo class.
Also in the hibernate mapping file what should be the datatype for the same property.
when i am running the file hibernate keeps on giving error like cannot do a conversion.
below are my pojo and .hbm file
public class destination implements Serializable{
private String configId;
private String isCurrent;
//other properties and getter, setters
}
destination.hbm.xml
<class name="com.testing" table="configuration">
<id name="configID" type="java.lang.Integer">
<column name="configuration_id" />
<generator class="identity" />
</id>
<property name="isCurrent" type="Not-SURE">
<column name="is_current" not-null="true" />
</property>
The column i am talking about is the isCurrent property in the pojo and .hbm.xml file.
Its defined as Varchar2(1 byte) in the db. I ma not sure about the datatype and marked it a String but the issue still persists.
I have searched the net but have not got any proper solution for this issue.
Can you please help me here as its really eating my head a lot.
I would focus on the configId you declared it as String in the class but as Integer in the xml.
<id name="configID" type="java.lang.Integer">
Im guessing you want to store current flag on the record. In that case you can do
public class destination implements Serializable{
private String configId;
private boolean current;
public boolean isCurrent() {
return current;
}
}
and hbm mapping like
<property name="current" type="yes_no">
<column name="is_current" not-null="true" />
</property>
I have a Picture:
public class Picture implements java.io.Serializable {
private byte[] picEncoded;
private String Name;
//etc
Is it's possible to move byte[] to another class without creating physically separated table in db? Do i need to use some inheritance strategy?
edit
Blob in separate entity:
pojo:
public class PictureBlob implements java.io.Serializable {
private Integer pictureBlobId;
private byte[] blob;
hbm::
<class name="PictureBlob" table="PICTURE">
<id name="pictureBlobId" type="int">
<column length="200" name="PictureID"/>
</id>
<property name="blob" type="byte[]" insert="false" update="false">
<column name="PicEncoded" not-null="false"/>
</property>
</class>
Picture:
hbm::
<one-to-one class="PictureBlob" constrained="true" name="pictureBlob" fetch="select"/>
How do i insert new pictures?
PictureBlob pictureBlob= new PictureBlob();
pictureBlob.setBlob(new byte[]{84,32,22});
Picture p = new Picture();
p.setPictureBlob(pictureBlob);
session.save(p);
inserts record where blob value is null.
Is it's possible to move byte[] to another class without creating
physically separated table in db?
Use component mapping which creates a composition relation between Picture and PictureBlob. Example:
<hibernate-mapping>
<class name="Picture" table="PICTURE">
<id name="pictureId" type="int">
<generator class="native" />
</id>
<component name="pictureBlob " class="PictureBlob" lazy="no-proxy">
<property name="pictureBlobId" column="PictureID" type="int" length="200" />
<property name="blob" type="byte[]" insert="false" update="false"column="PicEncoded"/>
</component>
</class>
</hibernate-mapping>
POJO
public class Picture implements java.io.Serializable {
private int pictureId;
private PictureBlob pictureBlob;
//Setters & Getters
}
public class PictureBlob implements java.io.Serializable {
private int pictureBlobId;
private byte[] blob;
//Setters & Getters
}
Also Note:
Use lazy="true" on , and mappings to enable lazy
loading of individual scalar value-typed properties (a somewhat exotic
case). Requires bytecode instrumentation of compiled persistent
classes for the injection of interception code. Can be overriden in
HQL with FETCH ALL PROPERTIES.
Use lazy="no-proxy" on single-valued associations to enable lazy
fetching without the use of a proxy. Requires bytecode instrumentation
for the injection of interception code.
Use lazy="extra" on collections for "smart" collection behavior, i.e.
some collection operations such as size(), contains(), get(), etc. do
not trigger collection initialization. This is only sensible for very
large collections.
See here for more info. on fetching strategies
Edited.
if you interested in using annotations instead of hbm you can take a look at these
http://docs.oracle.com/javaee/6/api/javax/persistence/Embeddable.html, this will exactly solve your purpose.
I think you could use something like this:
<class name="Picture">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<component name="pictureBlob" class="PictureBlob">
<property name="pictureBlobId"/>
<property name="blob"/>
<property name="picture"/>
</component>
</class>
This might need some edititng, but the idea is this:
You have a Picture class. This class has property name and property pictureBlob of type PictureBlob.
the component tag indicates the properties inside the component are mapped to the same table as Picture
I got this hibernate mapping:
<class name="CoverageTerm" table="coverage_term">
<composite-id name="id" class="CoverageTermPK">
<key-many-to-one name="productTerm" class="ProductTerm">
<column name="termtype_id"></column>
<column name="product_id" ></column>
</key-many-to-one>
<key-many-to-one name="productCoverage" class="ProductCoverage" column="product_coverage_id"></key-many-to-one>
</composite-id>
<property name="data"/>
</class>
This is a simple composite key mapping with a relation to table productCoverage and a composite key relation to productterm.
Now the problem comes in my search function:
public CoverageTerm getCoverageTermFromProductTermCoverage(ProductTerm productTerm, ProductCoverage productCoverage) {
Criteria critCt = getSession().createCriteria(CoverageTerm.class);
Criteria critCtId = critCt.createCriteria("id");
critCtId.add(Restrictions.eq("productTerm", productTerm));
critCtId.add(Restrictions.eq("productCoverage", productCoverage));
return (CoverageTerm) critCt.uniqueResult();
}
This should let me make a subcriteria on "id" (which is the primary key, CoverageTermPK) and add restrictions on it, but when I run it I get the error message:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.hibernate.QueryException: could not resolve property: productTerm of: CoverageTerm
This feels strange, shouldn't it get the CoverageTermPK there? If I try with a subcriteria on the "data" property the criterias work, I just don't seem to be able to get the PK on the "id" subcriteria.
Any ideas as to why this is happening?
Not sure about your specific class structure but try to add id this way instead of separate criteria:
Restrictions.eq("id.productTerm", productTerm);
Restrictions.eq("id.productCoverage", productCoverage);