I am using hibernate to insert objects of the class meal in a hsql DB It works fine if I only insert 1 object but as soon as I try to insert a second it gives me an error. Here is my code and the error:
public static void main(String[] args) {
Main obj = new Main();
Long mealId1 = obj.saveMeal("Pommes");
Long mealId2 = obj.saveMeal("Doener1");
}
public Long saveMeal(String mealName)
{
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction transaction = null;
Long mealId = null;
try {
transaction = session.beginTransaction();
Meal meal = new Meal(mealName);
mealId = (Long) session.save(meal);
transaction.commit();
} catch (HibernateException e) {
transaction.rollback();
e.printStackTrace();
} finally {
session.close();
}
return mealId;
}
package data;
import java.util.List;
import java.util.LinkedList;
public class Meal implements java.io.Serializable {
private long id;
private String name;
private List<Image> images;
private List<Review> reviews;
private Grouping grouping;
public Meal() {
}
public Meal(String mealName) {
name = mealName;
}
public Meal(long mealId, String mealName) {
id = mealId;
name = mealName;
}
public long getId() {
return id;
}
public void setId(long mealId) {
id = mealId;
}
public String getMealName() {
return name;
}
public void setMealName(String mealName) {
name = mealName;
}
public float getAvg() {
float avg = 0;
for (int i = 0; i < reviews.size(); i++)
{
avg = avg + reviews.get(i).getReviewPoints();
}
return avg;
}
public List<Image> getNumberImages(int number) {
assert (number >= 0);
return images.subList(0, number) ;
}
public List<Image> getImages() {
return images;
}
public void setImages(LinkedList<Image> images) {
this.images = images;
}
public List<Review> getReviews(int number) {
assert (number >= 0);
return reviews.subList(0, number) ;
}
public LinkedList<String> getAltNames() {
LinkedList<String> altNames = new LinkedList<String>();
LinkedList<Meal> altNameMeals = grouping.getMeals();
for (int i = 0; i < altNameMeals.size(); i++)
{
altNames.add(altNameMeals.get(i).getMealName());
}
return altNames;
}
public void addReview(Review review) {
if (!reviews.contains(review)) {
reviews.add(review);
}
}
public Grouping getGrouping() {
return grouping;
}
public void setGrouping(Grouping grouping) {
this.grouping = grouping;
}
public void addImage(Image image) {
if (!images.contains(image)) {
images.add(image);
}
}<hibernate-mapping>
<class name="data.Meal" table="MEAL">
<id name="id" type="long" access="field">
<column name="ID" />
<generator class="assigned" />
</id>
<property name="name" type="java.lang.String" access="field">
<column name="NAME" />
</property>
<list name="images" inverse="false" table="IMAGE" lazy="true" access="field">
<key>
<column name="ID" />
</key>
<list-index column="column_name" />
<one-to-many class="data.Image" />
</list>
<list name="reviews" inverse="false" table="REVIEW" lazy="true" access="field">
<key>
<column name="ID" />
</key>
<list-index></list-index>
<one-to-many class="data.Review" />
</list>
<many-to-one name="grouping" class="data.Grouping" fetch="join">
<column name="GROUPING" />
</many-to-one>
</class>
First is the main method 2nd the class to be persitet and 3rd the hibernate mapping for the class. This is the error message:
843 [main] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: -104, SQLState: 23505
843 [main] ERROR org.hibernate.util.JDBCExceptionReporter - integrity constraint violation: unique constraint or index violation; SYS_PK_10585 table: MEAL
843 [main] ERROR org.hibernate.event.def.AbstractFlushingEventListener - Could not synchronize database state with session
You declared that you want to assign values to id property manually (<generator class="assigned" />), but don't actually assign it.
So, you need to assign the value manually or declare different id generation strategy.
Related
I am new to hibernate. My goal is to get query results to an ArrayList but I keep getting the ERROR: HHH000091: Expected type: int, actual value: org.hibernate.collection.internal.PersistentSet
I strongly believe the problem is in my mapping, any help is appreciated.
Errors
ERROR: HHH000123: IllegalArgumentException in class: com.mycompany.mavenproject1.Medicamento, setter method of property: labJoin
Apr 07, 2017 10:23:10 AM org.hibernate.property.BasicPropertyAccessor$BasicSetter set
ERROR: HHH000091: Expected type: int, actual value: org.hibernate.collection.internal.PersistentSet
My HQL query:
from Medicamento as m left join from Laboratorio as l where l.codigoLab=m.codigoLab
Mapping XML:
<class name="com.mycompany.mavenproject1.Medicamento" table="MEDICAMENTO" schema="ADMINFARMACIA" optimistic-lock="version">
<id name="codigoMed" type="long">
<column name="CODIGO_MED" not-null="true"/>
<generator class="assigned" />
</id>
<property name="nombreComercial" type="string">
<column name="NOMBRE_COMERCIAL" length="100" not-null="true" />
</property>
<property name="codigoPrincipio" type="string">
<column name="CODIGO_PRINCIPIO" length="50" not-null="true" />
</property>
<property name="stockMinimo" type="java.lang.Integer">
<column name="STOCK_MINIMO" />
</property>
<property name="codigoLab" type="java.lang.Integer">
<column name="CODIGO_LAB" />
</property>
<property name="comentario" type="string">
<column name="COMENTARIO" length="1000" />
</property>
<property name="existencias" type="java.lang.Integer">
<column name="EXISTENCIAS"/>
</property>
<set name="labJoin" fetch="join">
<key column="CODIGO_LAB" />
<one-to-many class="com.mycompany.mavenproject1.Laboratorio"/>
</set>
</class>
Laboratorio.java:
public class Laboratorio implements java.io.Serializable{
private int codigoLab;
private String nombreLab;
public Laboratorio(){
}
public int getCodigoLab() {
return codigoLab;
}
public void setCodigoLab(int codigoLab) {
this.codigoLab = codigoLab;
}
public String getNombreLab() {
return nombreLab;
}
public void setNombreLab(String nombreLab) {
this.nombreLab = nombreLab;
}
}
Medicamento.java - in this one labJoin and labName are the fields on "Laboratorio" table
public class Medicamento implements java.io.Serializable{
private Long codigoMed;
private String nombreComercial;
private String codigoPrincipio;
private int stockMinimo;
private int codigoLab;
private String comentario;
private int existencias;
private int labJoin;
private String labName;
public Medicamento(){
}
public Long getCodigoMed() {
return codigoMed;
}
public void setCodigoMed(Long codigoMed) {
this.codigoMed = codigoMed;
}
public String getNombreComercial() {
return nombreComercial;
}
public void setNombreComercial(String nombreComercial) {
this.nombreComercial = nombreComercial;
}
public String getCodigoPrincipio() {
return codigoPrincipio;
}
public void setCodigoPrincipio(String codigoPrincipio) {
this.codigoPrincipio = codigoPrincipio;
}
public int getStockMinimo() {
return stockMinimo;
}
public void setStockMinimo(int stockMinimo) {
this.stockMinimo = stockMinimo;
}
public int getCodigoLab() {
return codigoLab;
}
public void setCodigoLab(int codigoLab) {
this.codigoLab = codigoLab;
}
public int getLabJoin() {
return labJoin;
}
public void setLabJoin(int labJoin) {
this.labJoin = labJoin;
}
public String getLabName() {
return labName;
}
public void setLabJoin(String labName) {
this.labName= labName;
}
public String getComentario() {
return comentario;
}
public void setComentario(String comentario) {
this.comentario = comentario;
}
public int getExistencias() {
return existencias;
}
public void setExistencias(int existencias) {
this.existencias = existencias;
}
}
Calling method
private void displayResult(List rl){
ArrayList<Object> oneRow = new ArrayList<Object>();
for (Object o: rl){
Medicamento medList = (Medicamento)o;
System.out.println(labList.getCodigoLab());
oneRow.add(medList.getCodigoMed());
oneRow.add(medList.getExistencias());
oneRow.add(medList.getNombreComercial());
oneRow.add(medList.getLabJoin());
}
LowStockTableModel model = new LowStockTableModel(oneRow);
try{
jTable1.setModel(model);
}
catch (Exception e){
JOptionPane.showMessageDialog(null, e.getLocalizedMessage(),"Error",JOptionPane.ERROR_MESSAGE);
jTextField1.setText("");
}
}
In your mapping, you have this
<set name="labJoin" fetch="join">
<key column="CODIGO_LAB" />
<one-to-many class="com.mycompany.mavenproject1.Laboratorio"/>
</set>
But property labJoin has type int. The type of this property has to be Set<Laboratorio>.
How to resolve this issue org.hibernate.AssertionFailure: null id in com.xxxxxx.Profiles entry (don't flush the Session after an exception occurs)
I'm using hibernate and Mysql, I want to insert the data into a table of my database but I was unable to do it.
Thanks.
This is my Dao:
public class ProfilesDao {
public void addProfile(Profiles profile){
Transaction tx = null;
Session session = HibernateUtil.getSessionFactory().openSession();
try{
tx = session.beginTransaction();
session.save(profile);
session.getTransaction().commit();
} catch (Exception e){
e.printStackTrace();
if(tx != null){
tx.rollback();
}
} finally {
session.flush();
session.close();
}
}
}
This is my Bean:
public void addProfile(){
Profiles profiles = new Profiles(getProfileName(),getProfileDescription());
ProfilesDao profilesDao = new ProfilesDao();
profilesDao.addProfile(profiles);
}
This is my POJO:
#Entity
#Table(name="profiles"
,catalog="metaestudiante_project_v1"
, uniqueConstraints = #UniqueConstraint(columnNames="profile_name")
)
public class Profiles implements java.io.Serializable {
private Short profileId;
private String profileName;
private String profileDescription;
private Set userses = new HashSet(0);
public Profiles() {
}
public Profiles(String profileName, String profileDescription) {
this.profileName = profileName;
this.profileDescription = profileDescription;
}
public Profiles(String profileName, String profileDescription, Set userses) {
this.profileName = profileName;
this.profileDescription = profileDescription;
this.userses = userses;
}
#Id #GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="profile_id", unique=true, nullable=false)
public Short getProfileId() {
return this.profileId;
}
public void setProfileId(Short profileId) {
this.profileId = profileId;
}
#Column(name="profile_name", unique=true, nullable=false, length=15)
public String getProfileName() {
return this.profileName;
}
public void setProfileName(String profileName) {
this.profileName = profileName;
}
#Column(name="profile_description", nullable=false, length=140)
public String getProfileDescription() {
return this.profileDescription;
}
public void setProfileDescription(String profileDescription) {
this.profileDescription = profileDescription;
}
#OneToMany(fetch=FetchType.LAZY, mappedBy="profiles")
public Set getUserses() {
return this.userses;
}
public void setUserses(Set userses) {
this.userses = userses;
}
}
And this is my hbm.xml
<hibernate-mapping>
<class name="com.besolapp.model.pojos.Profiles" table="profiles" catalog="metaestudiante_project_v1" optimistic-lock="version">
<id name="profileId" type="java.lang.Byte">
<column name="profile_id" />
<generator class="identity" />
</id>
<property name="profileName" type="string">
<column name="profile_name" length="15" not-null="true" unique="true" />
</property>
<property name="profileDescription" type="string">
<column name="profile_description" length="140" not-null="true" />
</property>
<set name="userses" table="users" inverse="true" lazy="true" fetch="select">
<key>
<column name="profile_id" not-null="true" />
</key>
<one-to-many class="com.besolapp.model.pojos.Users" />
</set>
</class>
</hibernate-mapping>
All this looks like easy but I am getting an error:
org.hibernate.AssertionFailure: null id in com.besolapp.model.pojos.Profiles entry (don't flush the Session after an exception occurs)
Can anybody help me please?
Problem Solved. Thank you.
Now I have three tables movie_information, release_company and rating.
movie_information and rating are having one-to-one relationship while release_company and movie_information are having one-to-many relationship.
I am trying to build a CMS with hibernate but I found that I am not able to correctly construct the part that involve these three tables.
Here comes my code
MovieInformation.java
public class MovieInformation {
private ReleaseCompany releaseCompany;
private Rating rating;
// Other data member
// Constructor, getter and setter
public ReleaseCompany getReleaseCompany(){
ReleaseCompany newReleaseCompany = new ReleaseCompany(this.releaseCompany);
return newReleaseCompany;
}
public Rating getRating(){
Rating newRating = new Rating(this.rating);
return newRating;
}
public void setReleaseCompany(ReleaseCompany releaseCompany){
this.releaseCompany = new ReleaseCompany(releaseCompany);
}
}
ReleaseCompany.java
public class ReleaseCompany {
private int releaseCompanyId;
private String releaseCompanyName;
private Set<MovieInformation> movies = new HashSet<MovieInformation>();
public ReleaseCompany(){
}
public ReleaseCompany(String releaseCompanyName){
this.releaseCompanyName = releaseCompanyName;
}
public ReleaseCompany(ReleaseCompany releaseCompany){
this.releaseCompanyName = releaseCompany.getReleaseCompanyName();
}
public Set<MovieInformation> getMovies() {
Set<MovieInformation> newMoviesSet = new HashSet<MovieInformation>(movies);
return newMoviesSet;
}
public void setMovies(Set<MovieInformation> movies) {
this.movies = new HashSet<MovieInformation>(movies);
}
// Other constructor, getter and setter
}
Rating.java
public class Rating {
private MovieInformation movie;
// other data member
public void setMovie(MovieInformation movie){
this.movie = new MovieInformation(movie);
}
// other constructor, getter and setter
}
MovieInformation.hbm.xml
<class name="cart.hibernate.movieInformation.MovieInformation" table="movie_information">
<id column="move_id" name="movieId" type="long">
<generator class="native"/>
</id>
<one-to-one name="rating" class="cart.hibernate.rating.Rating" cascade="save-update"></one-to-one>
<many-to-one name="releaseCompany" class="cart.hibernate.releaseCompany.ReleaseCompany" unique="false"><!-- constrained="true" -->
<column name="release_company_id" not-null="true" />
</many-to-one>
// Other property
</class>
Rating.hbm.xml
<class name="cart.hibernate.rating.Rating" table="rating">
<id name="movieId" type="java.lang.Long">
<column name="movie_id" />
<generator class="foreign">
<param name="property">movie</param>
</generator>
</id>
<property column="avg_rate" name="avgRate" type="double"/>
<property column="num_of_rate" name="numOfRate" type="long"/>
<one-to-one name="movie" class="cart.hibernate.movieInformation.MovieInformation" constrained="true"></one-to-one>
</class>
ReleaseCompany.hbm.xml
<class name="cart.hibernate.releaseCompany.ReleaseCompany" table="release_company">
<id column="release_company_id" name="releaseCompanyId" type="int">
<generator class="native"/>
</id>
<property column="release_company_name" name="releaseCompanyName" type="string"/>
<set name="movies" table="movie_information" inverse="true" lazy="true" fetch="select">
<key>
<column name="movie_id" not-null="true" />
</key>
<one-to-many class="cart.hibernate.movieInformation.MovieInformation" />
</set>
</class>
Testing Main method
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = null;
tx = session.beginTransaction();
Rating rating = new Rating(5.6, 80);
ReleaseCompany releaseCompany = new ReleaseCompany();
releaseCompany.setReleaseCompanyName("a");
session.save(releaseCompany);
// ReleaseCompany releaseCompany = (ReleaseCompany)session.get(ReleaseCompany.class, 15);
// Another testing case that I have tried. It throw another exception,
// if you need the information in this part, please let me know.
MovieInformation movie = new MovieInformation("Matrix", 150, 1, 50, date, releaseDate, "good description");
movie.setRating(rating);
movie.setReleaseCompany(releaseCompany);
rating.setMovie(movie);
session.save(movie); // <--- Error occur here
tx.commit();
StackTrace
org.hibernate.PropertyValueException: not-null property references a null or transient value: cart.hibernate.movieInformation.MovieInformation.releaseCompany
at org.hibernate.engine.Nullability.checkNullability(Nullability.java:100)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:312)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:203)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:129)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:56)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:50)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:713)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:701)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:697)
at cart.hibernate.movieInformation.ManageMovieInformation.main(ManageMovieInformation.java:61)
BUILD SUCCESSFUL (total time: 1 second)
I have read several similar question, some of the people said the releaseCompany(in my case) object hasn't saved to the database so the setReleaseCompany() cannot work as expected. I am not sure whether the releaseCompany object exist or not because I cannot see the record in MySql(I am not sure whether the record would be saved or not if exceptions are thrown). Moreover, some of them said the attribute of the mapping tag is not correct but I am not sure whether mine are correct or not.
I apologies to put so much code in the post, hope that you could solve this problem.
Keep it simple :
public class MovieInformation {
private ReleaseCompany releaseCompany;
private Rating rating;
// Other data member
// Constructor, getter and setter
public ReleaseCompany getReleaseCompany(){
return releaseCompany;
}
public Rating getRating(){
return rating;
}
public void setReleaseCompany(ReleaseCompany releaseCompany){
this.releaseCompany = releaseCompany;
}
}
public class ReleaseCompany {
private int releaseCompanyId;
private String releaseCompanyName;
private Set<MovieInformation> movies = new HashSet<MovieInformation>();
public ReleaseCompany(){
}
public ReleaseCompany(String releaseCompanyName){
this.releaseCompanyName = releaseCompanyName;
}
public ReleaseCompany(ReleaseCompany releaseCompany){
this.releaseCompanyName = releaseCompany.getReleaseCompanyName();
}
public Set<MovieInformation> getMovies() {
return movies;
}
private void setMovies(Set<MovieInformation> movies) {
this.movies = movies;
}
// Other constructor, getter and setter
}
public class Rating {
private MovieInformation movie;
// other data member
public void setMovie(MovieInformation movie){
this.movie = movie;
}
// other constructor, getter and setter
}
Please note that setMovies(Set movies) is private, so the only way to change all movies is to do something like this:
releaseCompany.getMovies().clear();
releaseCompany.getMovies().addAll(newMovieCollection);
You need to that because:
hibernate need to track the changes made to the collection
hibernate put a proxy around the collection to do this tracking.
replacing the Set by another one implies that the hibernate proxy will be lost
As I run my main class (Runner) program I get the following exception :
org.hibernate.id.IdentifierGenerationException: attempted to assign id
from null one-to-one property: country
I don't know the reason, why am I getting this exception.
The mapping xml :
<hibernate-mapping>
<class name="pojo.Country" table="country">
<id name="countryID" column="c_id">
<generator class="increment" />
</id>
<property name="countryName" column="c_name" />
<one-to-one class="pojo.PM" name="pm" cascade="all" />
</class>
<class name="pojo.PM" table="pm">
<id name="countryID" column="c_id">
<generator class="foreign">
<param name="property">country</param>
</generator>
</id>
<property name="pmName" column="pm_name" />
<one-to-one class="pojo.Country" name="country" constrained="true" />
</class>
</hibernate-mapping>
POJO Classes :
Country
public class Country {
private int countryID;
private String countryName;
private PM pm;
public PM getPm() {
return pm;
}
public void setPm(PM pm) {
this.pm = pm;
}
public int getCountryID() {
return countryID;
}
public void setCountryID(int countryID) {
this.countryID = countryID;
}
public String getCountryName() {
return countryName;
}
public void setCountryName(String countryName) {
this.countryName = countryName;
}
}
PM
public class PM {
private int countryID;
private String pmName;
private Country country;
public int getCountryID() {
return countryID;
}
public void setCountryID(int countryID) {
this.countryID = countryID;
}
public String getPmName() {
return pmName;
}
public void setPmName(String pmName) {
this.pmName = pmName;
}
public Country getCountry() {
return country;
}
public void setCountry(Country country) {
this.country = country;
}
}
and this is the class that tries to commit the transaction :
public class Runner {
public static void main(String args[]) {System.out.println("dfdf");
Configuration config = new Configuration().configure();
SessionFactory sessFact = config.buildSessionFactory();
Session session = sessFact.openSession();
Transaction trans = session.beginTransaction();
Country c = new Country();
PM pm = new PM();
pm.setPmName("Manmohan Singh");
c.setCountryName("India");
c.setPm(pm);
session.save(c);
trans.commit();
}
}
SQL that created table :
CREATE TABLE country(c_id INTEGER,c_name TEXT,PRIMARY KEY(c_id));
CREATE TABLE pm(c_id INTEGER,pm_name TEXT);
The problem is the country variable. You should initialize all the attirbutes before trying to do some transactions.
EDIT: In your Hibernate file, you want to generate the PM ID from the ID of the country property. However, this property has never been initialized.
<class name="pojo.PM" table="pm">
<id name="countryID" column="c_id">
<generator class="foreign">
<param name="property">country</param>
</generator>
</id>
<property name="pmName" column="pm_name" />
<one-to-one class="pojo.Country" name="country" constrained="true" />
</class>
So, add pm.setCountry(c); to your code.
This post is an continuation of this post
I have DlUser Class each object of this class may have DLFaceBook class and each object of DlFaceBook can have Friends which are mapped as myFriends.
I'm trying to map relation of the same class as many to many relation using bag mapping,composite primary key and static inner class. my code is the following:
public class DlUser{
public DlUser(){}
Long Id;
String FirstName;
String LastName;
....
DlFaceBook fbuser;
//// all requred
getters and setters...
}
The Facebook user class looks like this as you can see I have the collection of objectes with the class MyFriends:
public class DlFaceBook {
private long dlpId;
private String FbId;
private Collection<MyFriends> Friends;
public DlFaceBook(){}
public void setFbId(String FbId)
{
this.FbId = FbId;
}
public void setFriends(Collection<MyFriends> friends)
{
this.Friends = friends;
}
public Collection<MyFriends> getFriends()
{
return this.Friends;
}
public void setdlpId(long id)
{
this.dlpId = id;
}
public long getdlpId()
{
return this.dlpId;
}
public String getFbId()
{
return this.FbId;
}
}
MyFriends class looks like this:
public class MyFriends {
private MyFriendsId myFriendId;
private DlFaceBook me;
private DlFaceBook myFriend;
public MyFriendsId getmyFriendId(){
return this.myFriendId;
}
public void setmyFriendId(MyFriendsId fid){
this.myFriendId = fid;
}
public void setme(DlFaceBook me){
this.me = me;
}
public void setmyFriend(DlFaceBook friend){
this.myFriend = friend;
}
public DlFaceBook getme(){
return this.me ;
}
public DlFaceBook getmyFriend(){
return this.myFriend ;
}
public MyFriends(DlFaceBook me, DlFaceBook user){
this.me = me ;
this.myFriend = user;
this.myFriendId = new MyFriendsId(me.getdlpId(),user.getdlpId());
}
public static class MyFriendsId implements Serializable {
private long meId;
private long myFrId;
// getter's and setter's
public MyFriendsId() {}
public MyFriendsId(long meId, long myFriendId) {
this.meId = meId;
this.myFrId = myFriendId;
}
// getter's and setter's
public long getmeId(){
return this.meId;
}
public void setmeId(Integer id){
this.meId = id;
}
public long getmyFrId(){
return this.myFrId;
}
public void setmyFrId(long id){
this.myFrId = id;
}
}
}
Now the Mapping:
DlUser.hbm.xml is the following and it's simple:
<hibernate-mapping>
<class name="DlUser" table="Users">
<id name="Id" column="id" >
<generator class="sequence">
<param name="sequence">userseq</param>
</generator>
</id>
<property name="firstName">
<column name="FirstName" />
</property>
<property name="lastName">
<column name="LastName"/>
</property>
<many-to-one
name="FaceBook"
class="DlFaceBook"
cascade="all"
column="dlpId"
unique="true"
/>
</class>
</hibernate-mapping>
DlFacebook.hbm.xml looks like this:
<hibernate-mapping>
<class name="DlFaceBook" table="dlfacebook">
<id name="dlpId" type="java.lang.Long" column="dlpId">
<generator class="increment" />
</id>
<property name="fbId">
<column name="fbId" />
</property>
<bag name="Friends">
<key column="me_Id" />
<one-to-many class="MyFriends"/>
</bag>
</class>
</hibernate-mapping>
Then MyFriends.hbm.xml looks like this:
<hibernate-mapping>
<class name="MyFriends">
<composite-id name="myFriendId" class="MyFriends$MyFriendsId">
<key-property name="meId"/>
<key-property name="myFrId"/>
</composite-id>
<many-to-one name="me" class="DlFaceBook" insert="false" update="false"/>
<many-to-one name="myFriend" class="DlFaceBook" insert="false" update="false"/>
</class>
</hibernate-mapping>
When I'm executing my query I got the following error:
Hibernate: insert into dlfacebook (fbId, dlpId) values (?, ?)
Hibernate: insert into Users (FirstName, LastName, email, twitter, birthday, dlpId, id) values (?, ?, ?, ?, ?, ?, ?)
Hibernate: update MyFriends set me_Id=? where meId=? and myFrId=?
Hibernate: update MyFriends set me_Id=? where meId=? and myFrId=?
Oct 2, 2010 1:21:18 PM org.hibernate.jdbc.BatchingBatcher doExecuteBatch
SEVERE: Exception executing batch:
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:85)
at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:70)
at org.hibernate.jdbc.BatchingBatcher.checkRowCounts(BatchingBatcher.java:90)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:183)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1206)
at Test.main(Test.java:54)
Oct 2, 2010 1:21:18 PM org.hibernate.event.def.AbstractFlushingEventListener performExecutions
SEVERE: Could not synchronize database state with session
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:85)
at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:70)
at org.hibernate.jdbc.BatchingBatcher.checkRowCounts(BatchingBatcher.java:90)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:183)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1206)
at Test.main(Test.java:54)
Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
I see that this error happens when we trying to update not existing row, but how can I make this code work?
Just Facebook and MyFriends
Facebook Notice add convenience method and MutableLong (later, i tell you why to use MutableLong)
public class Facebook {
private MutableLong id = new MutableLong();
public Long getId() { return id.longValue(); }
public void setId(Long id) { this.id.setValue(id); }
public MutableLong getIdAsMutableLong() {
return id;
}
private Collection<MyFriends> myFriends = new ArrayList<MyFriends>();
public Collection<MyFriends> getMyFriends() { return myFriends; }
public void setMyFriends(Collection<MyFriends> myFriends) { this.myFriends = myFriends; }
/**
* add convenience method
*/
public void addFriend(Facebook myFriendFacebook) {
myFriends.add(new MyFriends(this, myFriendFacebook));
}
}
MyFriends
public class MyFriends {
private MyFriendsId myFriendId;
public MyFriendsId getmyFriendId(){ return this.myFriendId; }
public void setmyFriendId(MyFriendsId myFriendId){ this.myFriendId = myFriendId; }
private Facebook me;
public Facebook getme() { return this.me; }
public void setme(Facebook me){ this.me = me; }
private Facebook myFriend;
public Facebook getmyFriend() { return this.myFriend; }
public void setmyFriend(Facebook friend) { this.myFriend = friend; }
public MyFriends() {}
public MyFriends(Facebook meFacebook, Facebook myFriendFacebook){
this.me = meFacebook ;
this.myFriend = myFriendFacebook;
this.myFriendId = new MyFriendsId(meFacebook.getIdAsMutableLong(), myFriendFacebook.getIdAsMutableLong());
}
public static class MyFriendsId implements Serializable {
private MutableLong meId = new MutableLong();
public Long getMeId() { return this.meId.longValue(); }
public void setMeId(Long id) { this.meId.setValue(id); }
private MutableLong myFriendId = new MutableLong();
public Long getMyFriendId(){ return this.myFriendId.longValue(); }
public void setMyFriendId(Long id) { this.myFriendId.setValue(id); }
public MyFriendsId() {}
public MyFriendsId(MutableLong meId, MutableLong myFriendId) {
this.meId = meId;
this.myFriendId = myFriendId;
}
#Override
public boolean equals(Object o) {
if (!(o instanceof MyFriendsId))
return false;
MyFriendsId other = (MyFriendsId) o;
return new EqualsBuilder()
.append(getMeId(), other.getMeId())
.append(getMyFriendId(), getMyFriendId())
.isEquals();
}
#Override
public int hashCode() {
return new HashCodeBuilder()
.append(getMeId())
.append(getMyFriendId())
.hashCode();
}
}
}
Mapping
<hibernate-mapping package="br.com._3845772.model.domain">
<class name="User">
<id name="id">
<generator class="native"/>
</id>
<many-to-one cascade="all" class="Facebook" name="facebook"/>
</class>
<class name="Facebook">
<id name="id">
<generator class="native"/>
</id>
<bag cascade="all" name="myFriends">
<key column="ME_FACEBOOK_ID" update="false"/>
<one-to-many class="MyFriends"/>
</bag>
</class>
<class name="MyFriends">
<composite-id class="MyFriends$MyFriendsId" name="myFriendId">
<key-property column="ME_FACEBOOK_ID" name="meId"/>
<key-property column="MY_FRIEND_FACEBOOK_ID" name="myFriendId"/>
</composite-id>
<many-to-one class="Facebook" column="ME_FACEBOOK_ID" insert="false" name="me" update="false"/>
<many-to-one class="Facebook" column="MY_FRIEND_FACEBOOK_ID" insert="false" name="myFriend" update="false"/>
</class>
</hibernate-mapping>
And this sample
Facebook meFacebook = new Facebook();
Facebook myFriendFacebook = new Facebook();
meFacebook.addFriend(myFriendFacebook);
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(myFriendFacebook);
session.save(meFacebook);
session.getTransaction().commit();
session.close();
Which gives me
Hibernate: insert into Facebook values ( )
Hibernate: insert into Facebook values ( )
Hibernate: select myfriends_.ME_FACEBOOK_ID, myfriends_.MY_FRIEND_FACEBOOK_ID from MyFriends myfriends_ where myfriends_.ME_FACEBOOK_ID=? and myfriends_.MY_FRIEND_FACEBOOK_ID=?
Hibernate: insert into MyFriends (ME_FACEBOOK_ID, MY_FRIEND_FACEBOOK_ID) values (?, ?)
A couple of notes
Hibernate does not support automatic generation of composite primary key. You must set up its value before saving
Your database must support the target generator strategy (If you does not know which generator strategy your database support, prefer to use a native strategy)
Each entity must supply a no-arg constructor
Now why MutableLong (encapsulated by a Long property) instead of Long ?
Number and its subclasses (Long is a Number) are immutable. So if you want Facebook.id (configured by database) and its counterpart MyFriend$MyFriendId.meId share the same value, you must use MutableLong. When the database set up Facebook.id, MyFriend$MyFriendId.meId automatically get its newest value. But it just occurs if you use a MutableLong.