-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 
Author Message
 Post subject: Flushing cause not-null violation
PostPosted: Thu Jul 17, 2008 4:21 am 
Beginner
Beginner

Joined: Fri Aug 05, 2005 3:36 am
Posts: 28
Embarrassed to ask this.

I have a uni-directional many-to-one association. When I save a new object from the owning side (the many side), H tries to save it with a null in the association field.

It's like this. I've got some classes:

Code:
class Car {
  @Id etc...

  @ManyToOne
  @JoinColumn(nullable=false)
  Color color;
}

class Color {
   @Id etc...
}


The user is creating a car and has picked a color. My webapp receives a POST from the browser. I have a session factory and am using session per thread. The code goes something like this (of course it doesn't all actually happen in one method of one class...I'm just eliding the details)

Code:
factory.getCurrentSession().beginTransaction();
Car car = new Car();
Long colorId = ... (from the POST parameters)
Color color = (Color) session.createQuery("from Color where id=:id").setParameter("id", colorId).uniqueResult();
car.setColor(color);
session.save(car);
factory.getCurrentSession().getTransaction().commit();


And that's where it fails:

Code:
SEVERE: Servlet.service() for servlet FilterConfig threw exception
java.sql.BatchUpdateException: ORA-01400: cannot insert NULL into ("MySchema"."CAR"."COLOR_ID")

   at oracle.jdbc.driver.DatabaseError.throwBatchUpdateException(DatabaseError.java:566)
   at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:9365)
   at oracle.jdbc.driver.OracleStatementWrapper.executeBatch(OracleStatementWrapper.java:210)
   at org.apache.tomcat.dbcp.dbcp.DelegatingStatement.executeBatch(DelegatingStatement.java:297)
   at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)
   at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:246)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:167)
   at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
   at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
   at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
   at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
   at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
   at com.livevox.config.inputfilter.web.FrameworkServlet.commit(FrameworkServlet.java:54)
   at com.livevox.config.inputfilter.web.FilterConfigServlet.doService(FilterConfigServlet.java:45)
   at com.livevox.config.inputfilter.web.FilterConfigServlet.doPost(FilterConfigServlet.java:35)
   at javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
   at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
   at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
   at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
   at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
   at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
   at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
   at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
   at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
   at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
   at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
   at java.lang.Thread.run(Thread.java:619)


Through tracing I discovered that when I run the query, it triggers a flush, and it seems like at this point, the newly created Car object is stored in Hibernate/JDBC's internal stash of objects, without of course the Color. Then when I commit(), it finds that copy of Car and tries to save _it_, rather than the one I was using, which has a Color.

When I use FlushMode.COMMIT, this doesn't happen, but that causes me other problems, and why should I have to do that?

What is UP with this??

-Larry


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 17, 2008 7:19 am 
Newbie

Joined: Fri Mar 23, 2007 4:47 am
Posts: 16
Hi,

Ik kan confirm that I too am having this problem. I have an object with 4 properties. Lets call them property1, property2, property3 and property4. Properties 1, 2 and 3 are part of a composite id. The 4th is just a property.

When I use a HibernateTemplate and I try to update an object I get the same error as menthioned above. I have turned the Queries output to System.out' option on and I found out what the problem is. The update query that is being created is:

UPDATE TableName SET Property1=null, Property2=null, Property3=null WHERE Property1=? and Property2=? and Property3=?

I have debuged my application and I can confirm that all the properties are filled and aren't null. So the fact that the update query is trying to save all the properties to null is really strange.

Anybody have any ideas how to solve this?
Martyn


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 17, 2008 4:26 pm 
Beginner
Beginner

Joined: Fri Aug 05, 2005 3:36 am
Posts: 28
I have found what was the problem.

My Car was itself actually part of a Fleet:

class Fleet {

@OneToMany(cascade = ALL)
Set<Car> cars;
addCar(car) {...};
}

Note the 'cascade = ALL'.

The fleet is already persistent.

Before I set the color on the car, I add the car to the fleet:

fleet.add(car);
...
Long colorId = ... (from the POST parameters)
Color color = (Color) session.createQuery("from Color where id=:id").setParameter("id", car).uniqueresult();
setColor(color);

When I perform the query, the car is already reachable from the Fleet, and so the flush triggered by the query captures it.

But I didn't need to add the car to the fleet just yet; I can add it after I set the color.

Basically, I guess the rule is that if you're going to use flush = auto, you'd better have all your persistent objects (including those unsaved objects that are reachable from persistent objects that cascade their updates) in a consistent state.

Chapter 10.2 from the hibernate ref manual:

"If the object you make persistent has associated objects (e.g. the kittens collection in the previous example), these objects may be made persistent in any order you like unless you have a NOT NULL constraint upon a foreign key column. There is never a risk of violating foreign key constraints. However, you might violate a NOT NULL constraint if you save() the objects in the wrong order."

Then again, I don't call save() on anything until it's all in a consistent state. In fact I only call save on the fleet. Why doesn't hibernate see that I've updated the car since the previous flush, and use its transitive persistence magic to save _that_ version of the car, instead of my old version?

-Larry


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jul 19, 2008 9:36 am 
Expert
Expert

Joined: Tue May 13, 2008 3:42 pm
Posts: 919
Location: Toronto & Ajax Ontario www.hibernatemadeeasy.com
Awesome explaination. Thanks for the update!

_________________
Cameron McKenzie - Author of "Hibernate Made Easy" and "What is WebSphere?"
http://www.TheBookOnHibernate.com Check out my 'easy to follow' Hibernate & JPA Tutorials


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.