针对这次一对多,多对一,多对多,一对一的问题来进行研究。
在第一次使用的时候,遇到如下问题:
1..不知如何配置,一对多该怎么配置?
答:在一的一方进行配置,配置条件@JoinColumn,其name属性值是在多的一方对应的字段。其不能为id主键。
2.JoinColumn和Column共存的问题,属性name一样的问题。
答:他们的name属性如果一样,就相当于有两个控制同一个,那是肯定会出现问题的,所以要想控制,其实除了改变name属性以外还可以控制其不能修改和删除就行了。如:@Column(name = "classification_id")
private Integer classificationId;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "classification_id",insertable = false,updatable = false)
private Classification theClassification;
3.是fetch = FetchType.LAZY的问题
答:在初期用一对多...的时候出现,用了Lazy,然后出现这么个错误:
org.hibernate.LazyInitializationException failed to lazily initialize....no session
然后我就换成FetchType.Eager最后用一对多等方法的时候可以用了,但是当我再给另一个字段添加属性FetchType.Eager的时候,出现错误了,不能有多个。这时就只能放弃用Eager了,向Lazy下手。最后找到了办法,那就是在web.xml中加入:
<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
就可以了。
4.最后又出现了新的问题。那就是在查询和修改皆可以,但是删除不行。删除就出现下面问题:
Method public java.lang.String org.hibernate.exception.NestableRuntimeException.getMessage(int) threw an exception when invoked on org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions
The problematic instruction:
----------
修改时没问题,但是删除时出现问题。一对多多对一。
==> ${msg[0]} [on line 68, column 29 in org/apache/struts2/dispatcher/error.ftl]
----------
Java backtrace for programmers:
----------
freemarker.template.TemplateModelException: Method public java.lang.String org.hibernate.exception.NestableRuntimeException.getMessage(int) threw an exception when invoked on org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions
at freemarker.ext.beans.SimpleMethodModel.exec(SimpleMethodModel.java:130)
at freemarker.ext.beans.SimpleMethodModel.get(SimpleMethodModel.java:138)
......
Caused by: java.lang.NullPointerException
这个原因是因为事物没有配置好。我用的是声明式事物的方法来解决这个问题。
在hibernate.xml中加入:
<!-- 事务管理对象 -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory"/>
</property>
</bean>
在service.xml中加入:
xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
然后加入:
<tx:annotation-driven transaction-manager="transactionManager" />
然后在serviceImpl.java中加入@Transactional,这个是用来管理整个类的标识,所以要放在类前面声明。
一波三折,最后问题解决了。透过这个问题,了解到了自己的不足。虽然百度是好,但是由于自己和别人配置的不一样,会出现一个问题,多个解决方法。针对这种情况,要认清问题的本质,不能盲目的看别人的代码。就比如说这个问题,如果先开始就从事物管理开始下手,那么就会节约大量的时间。这个问题主要就两点,一个是Lazy,一个是声明式事物管理。