开发者

Spring, Hibernate - many-to-many - update error

I'm trying to use many-to-many relation in Hibernate Framework, but I have some troubles.

I have 2 models.

User:

@Entity
public class User implements Serializable {
Long id;
String name;
List<Car> cars;
public User() {

}
public Long getId() {
    return id;
}
public void setId(Long id) {
    this.id = id;
}
public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}
public List<Car> getCars() {
    return cars;
}
public void setCars(List<Car> cars) {
    this.cars = cars;
}
}

Car:

@Entity
public class Car implements Serializable {
Long id;
String mark;
public Car() {

}
public Long getId() {
    return id;
}
public void setId(Long id) {
    this.id = id;
}
public String getMark() {
    return mark;
}
public void setMark(String mark) {
    this.mark = mark;
}
}

I followed by clues on this page, so my configuration files looks like this:

User:

<hibernate-mapping>
<class name="com.bontade.phone_book.mvc.spring.models.User" table="USERS">
    <id name="id" type="java.lang.Long">
        <column name="ID" />
        <generator class="identity" />
    </id>        
    <property name="name" not-null="true" length="100" type="java.lang.String">
        <column name="NAME" />
    </property>       
    <list name="cars" table="USER_CAR" cascade="all">
        <key>
            <column name="USER_ID" />
        </key>
        <list-index></list-index>
        <many-to-many column="CAR_ID" class="com.bontade.phone_book.mvc.spring.models.Car" />
    </list>        
</class>
</hibernate-mapping>

Car:

<hibernate-mapping>
<class name="com.bontade.phone_book.mvc.spring.models.Car" table="CARS">
    <id name="id" type="java.lang.Long">
        <column name="ID" />
        <generator class="identity" />
    </id>
    <property name="mark"  not-null="true" length="20" type="java.lang.String">
        <column name="MARK" />
    </property>     
</class>
</hibernate-mapping>

I'm getting errors:

    Hibernate: update CARS set MARK=? where ID=?
2011-02-23 16:32:34 org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/PhoneBook] threw exception [Request processing failed; nested exception is org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1; nested exception is org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1] with root cause
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:266)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:168)
    at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1028)
    at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:366)
    at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
    at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:655)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:732)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:701)
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140)
    at com.bontade.phone_book.mvc.spring.models.dao.implementations.CarDAOImplementation.saveCar(CarDAOImplementation.java:30)
    at com.bontade.phone_book.mvc.spring.controllers.HomePageController.handleRequestInternal(HomePageController.java:43)
    at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
    at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:875)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:807)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:501)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:306)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:96)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:244)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:108)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:558)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:379)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:243)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:259)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:281)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:662)

Update

public class CarAOImplementation implements CarDAO {

private HibernateTemplate hibernateTemplate;
private TransactionTemplate transactionTemplate;
public void setSessionFactory(SessionFactory sessionFactory) {
    this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}
public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
    this.transactionTemplate = 开发者_如何学PythontransactionTemplate;
}

@Override
public void saveCar(final Car car) {
    // TODO Auto-generated method stub
    this.transactionTemplate.execute(new TransactionCallback() {

        public Object doInTransaction(TransactionStatus transactionStatus) {
            try {
                hibernateTemplate.saveOrUpdate(car);
            } catch (Exception e) {
                transactionStatus.setRollbackOnly();
            }
            return null;
        }
    });
}
...
}

Update 2

Car markCar = new Car();
markCar.setId(null);
markCar.setMark("111");
carDAO.saveCar(markCar);

User mark = new User();
mark.setId(null);
mark.setName("mark");
List a = new ArrayList<Car>();
a.add(markCar);
mark.setCars(a);
userDAO.saveUser(mark);
List<User> users = userDAO.getAll();
System.out.println("==" + users.size() + "===");
System.out.println(users.get(0).getCars().get(0).getMark());

Stack trace:

    Hibernate: select user0_.ID as ID0_, user0_.NAME as NAME0_ from USERS user0_
==1==
2011-02-23 17:35:10 org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/PhoneBook] threw exception [Request processing failed; nested exception is org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.bontade.phone_book.mvc.spring.models.User.cars, no session or session was closed] with root cause
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.bontade.phone_book.mvc.spring.models.User.cars, no session or session was closed
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)
    at org.hibernate.collection.AbstractPersistentCollection.readElementByIndex(AbstractPersistentCollection.java:173)
    at org.hibernate.collection.PersistentList.get(PersistentList.java:293)
    at com.bontade.phone_book.mvc.spring.controllers.HomePageController.handleRequestInternal(HomePageController.java:59)
    at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
    at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:875)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:807)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:501)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:306)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:96)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:244)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:108)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:558)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:379)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:243)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:259)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:281)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:662)


Do not set the CarId by hand!

Car markCar = new Car();
markCar.setId(1L);  //<-- remove this line
markCar.setMark("111");
carDAO.saveCar(markCar);

remove this line, and try it again.

The reason is that hibernate use the primary key value to determine if it is an unsaved instance (in normal case NULL mean unsaved). So I guess that setting the car id to an value (different null) bemused Hibernate.

ADDED

An other thing that bemused me is that you use Annotations and XML.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜