I have the following three classes:
public class Student {
private Integer studentId;
private StudentSchool studentSchool;
private School school;
public Integer getStudentId() {
return studentId;
}
public void setStudentId(Integer studentId) {
this.studentId = studentId;
}
public StudentSchool getStudentSchool() {
return studentSchool;
}
public School getSchool() {
return school;
}
public void setSchool(School school) {
this.school = school;
}
}
public class StudentSchool {
private Student student;
private School school;
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
public School getSchool() {
return school;
}
public void setSchool(School school) {
this.school = school;
}
}
public class School {
private Integer schoolId;
private Set allStudents;
public Integer getSchoolId() {
return schoolId;
}
public void setSchoolId(Integer schoolId) {
this.schoolId = schoolId;
}
public Set getAllStudents() {
return allStudents;
}
public void setAllStudents(Set allStudents) {
this.allStudents = allStudents;
}
}
I have the following DDL:
create table Student (StudentId Integer);
create table StudentSchool (SchoolId Integer, StudentId Integer);
create table School (SchoolId Integer Primary Key);
I have the following HBM files:
School.hbm.xml
<hibernate-mapping>
<class name="School" table="School">
<property name="schoolId" type="integer" />
<set name="allStudents" table="StudentSchool" fetch="join">
<key column="schoolId" />
<composite-element class="StudentSchool">
<parent name="school"/>
<many-to-one name="student" column="studentId" not-null="true" class="Student" />
</composite-element>
</set>
</class>
</hibernate-mapping>
Student.hbm.xml
<hibernate-mapping>
<class name="Student" table="Student">
<property name="studentId" type="integer" />
<one-to-one name="studentSchool" class="StudentSchool" />
<!-- <one-to-one name="school" class="School" /> -->
</class>
</hibernate-mapping>
When I try to query the Student object based on the school, I get the following exception (even though I have a class called "StudentSchool" compiled in my classpath):
org.hibernate.MappingException: persistent class not known: StudentSchool
If I uncomment the one-to-one mapping to "School" and comment out the one-to-one mapping to "studentSchool", I get the following exception:
<AST>:1:143: unexpected AST node: : java.lang.NullPointerException
Does anyone have any ideas about what I did wrong with my hbm mapping? Thanks!
You should give the fully qualified name of your classes in the hbm files.
like somepackage.StudentSchool
EDIT: If all are in the same package, then try adding this
<hibernate-mapping>
<class name="Student" table="Student">
<property name="studentId" type="integer" />
<one-to-one name="studentSchool" class="StudentSchool" property-ref="student"/>
<!-- <one-to-one name="school" class="School" property-ref="student"/> -->
</class>
</hibernate-mapping>
Related
I have two tables - Student and Address. They have one to many relationship. Student entity is having collection of address entity. When i updating collection of address in student. Its not updating the data and giving this error. When i was updating the parent entity with child collection, its taking next to be incremented key which is not in the database. -
Exception in thread "main" org.hibernate.exception.ConstraintViolationException: could not execute statement
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:129)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:124)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:189)
at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:59)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3079)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3521)
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:88)
at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:395)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:387)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:303)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:349)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1195)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:404)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175)
at com.HibernateExample.test.HibernateTest.main(HibernateTest.java:51)
Caused by: org.postgresql.util.PSQLException: ERROR: insert or update on table "address" violates foreign key constraint "student_fk"
Detail: Key (id)=(5) is not present in table "student".
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2476)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2189)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:300)
at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:428)
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:354)
at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:169)
at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:136)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:186)
... 14 more
Student.java
public class Student {
public int id;
public String firstName;
public String lastName;
public int age;
public Set<Address> address = new HashSet<>(0);
public Set<Address> getAddress() {
return address;
}
public void setAddress(Set<Address> address) {
this.address = address;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Address.java
public class Address {
public int id;
public String streetName;
public String cityName;
public String stateName;
public String plotNo;
public Student student;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getStreetName() {
return streetName;
}
public void setStreetName(String streetName) {
this.streetName = streetName;
}
public String getCityName() {
return cityName;
}
public void setCityName(String cityName) {
this.cityName = cityName;
}
public String getStateName() {
return stateName;
}
public void setStateName(String stateName) {
this.stateName = stateName;
}
public String getPlotNo() {
return plotNo;
}
public void setPlotNo(String plotNo) {
this.plotNo = plotNo;
}
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
}
HibernateTest.java
public class HibernateTest {
public static void main(String[] args) {
Configuration configuration = new Configuration();
configuration.configure("hibernate-cfg.xml");
#SuppressWarnings("deprecation")
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
session.setFlushMode(FlushMode.COMMIT);
System.out.println(session.getFlushMode().name());
Transaction transaction = session.beginTransaction();
Student student = (Student) session.get(Student.class, 3);
Address address = new Address();
address.setStateName("Kerala");
address.setCityName("Old Delhi");
address.setStreetName("Uttaam Nagar");
address.setPlotNo("158A");
address.setStudent(student);
student.getAddress().add(address);
session.update(student);
transaction.commit();
session.close();
sessionFactory.close();
}
}
address.hbm.xml
<hibernate-mapping>
<class name="com.HibernateExample.entity.Address" table="address">
<meta attribute="class-description">
This class contains the address detail.
</meta>
<id name="id" type="int" column="id">
<generator class="increment" />
</id>
<property name="streetName" column="street_name" type="string"/>
<property name="cityName" column="city_name" type="string"/>
<property name="stateName" column="state_name" type="string"/>
<property name="plotNo" column="plot_no" type="string"/>
<many-to-one name="student" class="com.HibernateExample.entity.Student" >
<column name="student_id" not-null="true"></column>
</many-to-one>
</class>
</hibernate-mapping>
student.hbm.xml
<hibernate-mapping>
<class name="com.HibernateExample.entity.Student" table="student">
<meta attribute="class-description">
This class contains the student detail.
</meta>
<id name="id" type="int" column="id">
<generator class="increment" />
</id>
<property name="firstName" column="first_name" type="string" length="40" />
<property name="lastName" column="last_name" type="string" length="40" />
<property name="age" column="age" type="int"/>
<set name="address" cascade="all">
<key column="student_id"/>
<one-to-many class="com.HibernateExample.entity.Address"/>
</set>
</class>
</hibernate-mapping>
From the Session javadoc, Session.update() is specified to work with a detached entity instance. "If there is a persistent instance with the same identifier, an exception is thrown." Exactly which exception is not specified, and cascading might send it down a complex code path, which could result in this error.
The Student object you modify is not detached, but rather persistent, because you got it by loading from the Session and have not closed the Session or done anything else that would detach it. This means that all modifications to it are saved to the database automatically, with no need for any manual call on Session. This is specified in the class javadoc for Session, with the sentence "Changes to persistent instances are detected at flush time and also result in an SQL UPDATE."
Simply delete the line session.update(student);, and I think your code will start working, including saving the new address through the cascaded relationship when you commit the transaction.
It's been a while since I've worked with cascades so I'm not entirely certain, but you might also need to set cascade on the other side of the relationship.
The "student_id" is not associated with any of your primary keys. If "student_id" exists in both Student and Address tables then change this line in your student mapping file from "id" to "student_id":
<id name="id" type="int" column="student_id">
Double check your database table with a database table viewer/browser.
It seems you try to insert an ID that already exists in the database (5)
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?
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.
I am facing problem of org.hibernate.PropertyValueException: not-null property references a null or transient value: com.master.model.AccountLoan.account.
There are two table Accout and AccountLoan, below is table structure for Account
Account--
create table ACCOUNT
(
ac_id INTEGER not null,
ac_name VARCHAR2(40) not null,
ac_islocked CHAR(1) not null
)
below is table structure for Account Loan
AccountLoan--
create table ACCOUNT_LOAN
(
al_id INTEGER not null,
al_ac_id INTEGER not null,
al_loanA NUMBER(15,2),
al_loanB NUMBER(15,2)
)
For both table data is comming from single jsp on single add button click. Add functionality is working fine.Account loan is optional, if user do not fill LoanA and LoanB field then no record is in account loan,if user fill LoanA and LoanB field then record is insert in account loan table.
Aim
I want update account record which have not account loan.When i am updating account record following exception is throwing--
org.hibernate.PropertyValueException: not-null property references a null or transient value: com.master.model.AccountLoan.account.
Below is Both model java file.
import java.math.BigDecimal;
public class Account extends BaseM
{
private String name;
private Boolean isLocked;
private AccountLoan accountLoan;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public Boolean getIsLocked()
{
return isLocked;
}
public void setIsLocked(Boolean isLocked)
{
this.isLocked = isLocked;
}
public AccountLoan getAccountLoan()
{
return accountLoan;
}
public void setAccountLoan(AccountLoan accountLoan)
{
this.accountLoan = accountLoan;
}
}
Account Loan model java file
import java.math.BigDecimal;
public class AccountLoan extends BaseM
{
private BigDecimal loanA;
private BigDecimal loanB;
private Account account;
public BigDecimal getloanA()
{
return loanA;
}
public void setloanA(BigDecimal loanA)
{
this.loanA= loanA;
}
public BigDecimal getloanB()
{
return loanB;
}
public void setLoanInterest(BigDecimal loanB)
{
this.loanB= loanB;
}
public Account getAccount()
{
return account;
}
public void setAccount(Account account)
{
this.account = account;
}
}
Account.hbm.xml
<hibernate-mapping>
<class name="com.master.model.Account" table="ACCOUNT" dynamic-update="true">
<id name="id" column="AC_ID" type="long">
<generator class="com.common.support.IdGenerator">
<param name="sequence">ACID_SEQ</param>
</generator>
</id>
<one-to-one name="accountLoan" class="com.master.model.AccountLoan" cascade="all"/>
<property name="name" column="AC_NAME" type="string" />
<property name="isLocked" column="AC_ISLOCKED" type="yes_no" />
</class>
</hibernate-mapping>
AccountLoan.hbm.xml
<hibernate-mapping>
<class name="com.master.model.AccountLoan" table="ACCOUNT_LOAN" dynamic-update="true">
<id name="id" column="AL_ID" type="long">
<generator class="com.common.support.IdGenerator">
<param name="sequence">ALID_SEQ</param>
</generator>
</id>
<many-to-one name="account" class="com.master.model.Account" unique="true">
<column name="AL_AC_ID" not-null="true" />
</many-to-one>
<property name="loanA" column="AL_LOANA" type="big_decimal" />
<property name="loanB" column="AL_LOANB" type="big_decimal" />
</class>
</hibernate-mapping>
First of all, make your mapping look like described in the documentation. The one-to-one needs a property-ref attribute.
Then, make sure that you initialize the AccountLoan.account property when you want to attach an AccountLoan to an Account. Initializing the Account.accountLoan field is not sufficient.
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.