问题描述
有两个问题:1、spring和hibernate中的一对多问题(包括添加、删除和更行)~我现在这么写代码规范吗?2、总感觉项目里加了spring之后,处理事务的速度变得慢了很多~比只是加入hibernate的时候慢~这是神马原因呢?数据库有两个表:“user”和“order”;一个“user”对应多个“order”;user表的外键关联在“order”表中具体的Dao借口都继承了泛型的Dao(泛型Dao里面有spring的数据操作)现在我想在“order”里面添加数据~测试结果现在添加失败~但没有Exception;以下是我的代码,问题应该就在“OrderServiceImpl”中;(Spring:ApplicationContext.xml) 1. <!-- <Tables> --> 2. <bean id="Users" class="com.beans.properties.User"></bean> 3. <bean id="Order" class="com.beans.properties.Order"></bean> 4. <!-- </Tables> --> 5. 6. <!-- <GenericDao> --> 7. <bean id="GenericDao" class="com.dao.GenericDaoImpl.GenericHibernateDaoImpl"> 8. <property name="sessionFactory"> 9. <ref bean="sessionFactory" /> 10. </property> 11. </bean> 12. <!-- </GenericDao> --> 13. 14. <!-- <Dao> --> 15. <bean id="UserDao" class="com.hibernate.daoImpl.UserDaoImpl"> 16. <property name="sessionFactory"> 17. <ref bean="sessionFactory" /> 18. </property> 19. </bean> 20. <bean id="OrderDao" class="com.hibernate.daoImpl.OrderDaoImpl"> 21. <property name="sessionFactory"> 22. <ref bean="sessionFactory" /> 23. </property> 24. </bean> 25. <!-- </Dao> --> 26. 27. <!-- <Service> --> 28. <bean id="UserService" class="com.hibernate.ServiceImpl.UserServiceImpl"> 29. <property name="dao"> 30. <ref bean="UserDao" /> 31. </property> 32. </bean> 33. 34. <bean id="OrderService" class="com.hibernate.ServiceImpl.OrderServiceImpl"> 35. <property name="orderDao"> 36. <ref bean="OrderDao" /> 37. </property> 38. <property name="userDao"> 39. <ref bean="UserDao" /> 40. </property> 41. <property name="userService"> 42. <ref bean="UserService" /> 43. </property> 44. </bean> 45. <!-- </Service> --> User.hbm.xml 1. <class name="com.beans.properties.User" table="user" catalog="test"> 2. <id name="userId" type="java.lang.Integer"> 3. <column name="userID" /> 4. <generator class="native" /> 5. </id> 6. <property name="userName" type="java.lang.String"> 7. <column name="userName" length="10" not-null="true" /> 8. </property> 9. <set name="orders" inverse="true" cascade="all"> 10. <key> 11. <column name="o_uID" /> 12. </key> 13. <one-to-many class="com.beans.properties.Order" /> 14. </set> 15. </class> Order.hbm.xml 1. <class name="com.beans.properties.Order" table="order" catalog="test"> 2. <id name="orderId" type="java.lang.Integer"> 3. <column name="orderID" /> 4. <generator class="native" /> 5. </id> 6. <many-to-one name="user" class="com.beans.properties.User" fetch="select"> 7. <column name="o_uID" /> 8. </many-to-one> 9. <property name="orderStatue" type="java.lang.Integer"> 10. <column name="order_statue" not-null="true" /> 11. </property> 12. <property name="orderName" type="java.lang.String"> 13. <column name="orderName" length="10" /> 14. </property> 15. <property name="version" type="java.lang.Integer"> 16. <column name="version" not-null="true" /> 17. </property> 18. </class> OrderDaoImpl(向数据库底层添加数据)public class OrderDaoImpl extends GenericHibernateDaoImpl<Order,Integer> implements OrderDao {boolean success =false;public boolean addOrder(Order order) {success=saveObj(order);System.out.println("save order");return success;}OrderServiceImpl(这层和用户沟通~问题出现在这代码当中:第16~19行) 1. public boolean addOrder(String orderName, Integer orderStatue, 2. String userName,Integer version) { 3. ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); 4. Order order = (Order)ctx.getBean("Order"); 5. userService = (UserService) ctx.getBean("UserService"); 6. orderDao=(OrderDao)ctx.getBean("OrderDao"); 7. 8. boolean success = false; 9. 10. Integer userId = userService.findUserId(userName);//get a UserID by userName 11. User user = userService.findUser(userId);//get an User by UserID 12. 13. order.setOrderName(orderName); 14. order.setOrderStatue(orderStatue); 15. order.setVersion(version); 16. order.setUser(user);//set an "user" into the order; 17. 18. try { 19. success=orderDao.addOrder(order);//保存“order”结果提示返回的“success”值为“false”,应该怎么办好呢? 20. } catch (Exception e) { 21. success = false; 22. e.printStackTrace(); 23. } 24. 25. return success; 26. } 如果单单用sql语句是可以插入的~但是我想用hibernate的特性把参数值set进去~thanks 问题补充:langshao 写道
解决方案
引用现在经你提点,一对多添加数据确实成功了~然而有新问题出现~我原来的思路是先查找出一个User~然后再根据这个User来添加他的Order~应该只是在Order表里面新增数据才合理~但是按照我写的程序~问题是:User表里同样会新增一个同名的User(只是ID不同)~新插入的Order所关联的User也是新增的那个同名User~这样的结果是不合符程序设计的原意~出现此问题的原因是:在执行完泛型Dao的Save()方法后 session被关闭了~难道又要想hibernate那样把所有事物都放在BeginTransaction()和commit()当中完成吗?这样做会出现很多重复的代码~不符合设计的原则吧~希望你能够指点一下~ 这一整个应该在一个事务中啊,在这个事务提交之前,session不会关闭。User user = userService.findUser(userId);//get an User by UserID order.setUser(user); user.addOrcer(order); updateUser(user); // 这应该是update
解决方案二:
引用1、现在我这么写代码规范吗? 2、为什么加入spring总感觉那个速度好像慢了很多的?1. 你这样写确实有问题,如:public boolean addOrder(String orderName, Integer orderStatue, String userName,Integer version) { ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); Order order = (Order)ctx.getBean("Order"); userService = (UserService) ctx.getBean("UserService"); orderDao=(OrderDao)ctx.getBean("OrderDao"); 这应该用注入,而不是在方法里获取。建议看看 springside是怎么写的。2. 用Spring不会让你的应用慢下来。可能是事务的问题吧,把不需要事务的方法,不要用事务或者设置事务为readonly。
解决方案三:
引用但是在userService.findUser(userId)里面我继承了spring的getHibernateTemplate的方法~这方法运行完之后不是会执行一个session.close()吗?因此我再执行一个saveUser()之后不就会重新调用getHibernateTemplate.save()的方法再开一个session吗?hibernateTemplate里用的session,如果是在事务中的,不会新开一次,而是直接用事务那个,在完成后也不会关闭session,而是留给事务来关。
解决方案四:
public boolean saveObj(T entity) { try { getHibernateTemplate().save(entity); success = true; } catch (HibernateException he) { he.printStackTrace(); success = false; throw he; } return success; } 这里是不是有问题?抛出的异常是:org.springframework.dao.DataAccessException应该是用以下某一个来捕捉才对,而不是HibernateException吧org.springframework.dao.DataAccessExceptionRuntimeExceptionException你调试一下,应该没进入这一段: catch (HibernateException he) { he.printStackTrace(); success = false; throw he; }
解决方案五:
你现在是一对多,那么操作是由一来完成对吧?一般的将”一”这一端设置为inverse=”false”,cascade=”all” ,这样一般的操作只需要在”一”这一端操作,此适合于标志性一对多的情况而Inverse=”true”的表示两个实体的关系由对方去维护。
解决方案六:
整个配置文件都没有看到spring的事务配置,你的配置了。贴出来看看
解决方案七:
User user = userService.findUser(userId);//get an User by UserID order.setUser(user);user.addOrcer(order);saveUser(user); // 调dao保存// saveOrder(order); // 这句应该可写、可不写。
解决方案八:
引用就是连异常都没有输出没有提交到数据库,可能是事务的问题。在orderDao.addOrder(order);之前先保存另外一个表的数据试试能不能成功。
解决方案:
<bean id="Users" class="com.beans.properties.User"></bean> <bean id="Order" class="com.beans.properties.Order"></bean>Spring中Bean默认是单例对象,如果你这样写,那么相当于:Users user = new Users();Order order = new Order();然后到无论到哪里要创建、或使用User或Oorder对象,你就直接拿上面的user和order,这样肯定有问题应该把这两行bean删除,在用到的地方new一个对象
解决方案:
把异常贴出来看看,如何有的话。
解决方案:
public boolean saveObj(T entity) { try { getHibernateTemplate().save(entity); success = true; } catch (HibernateException he) { he.printStackTrace(); success = false; throw he; // 出错时抛出异常,能返回false吗? } return success; // 这是一个类变量?多线程时,返回的是什么谁也不知道。}
解决方案:
数据库中有没有那条记录了?GenericHibernateDaoImpl中的saveObj贴出来看看。