小弟最近在研究hibernate3.3中用注解一对多双向的用法.遇到了一些问题,代码如下:
一的一端代码:package com.wang.sprhiber.pojo;import java.util.Set;
import java.util.TreeSet;import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;@Entity
@Table(name = "classes")
public class Classes
{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int cid;
@Column(name = "cname", nullable = true, length = 255)
private String cname; @OneToMany(mappedBy ="classes",fetch=FetchType.EAGER)
@OrderBy("mname")
private Set<Member> memSet = new TreeSet<Member>(); public Set<Member> getMemSet()
{
return memSet;
} public void setMemSet(Set<Member> memSet)
{
this.memSet = memSet;
} public int getCid()
{
return cid;
} public void setCid(int cid)
{
this.cid = cid;
} public String getCname()
{
return cname;
} public void setCname(String cname)
{
this.cname = cname;
}}多的一端代码:package com.wang.sprhiber.pojo;import java.util.Date;import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;import org.hibernate.annotations.Type;@Entity
@Table(name = "member")
public class Member implements Comparable<Member>
{
@Id
@Type(type = "java.lang.Integer")
@GeneratedValue(strategy = GenerationType.AUTO)
private int mid;
@Column(name = "mname", nullable = true, length = 40)
@Type(type = "java.lang.String")
private String mname;
@Type(type = "java.util.Date")
@Column(name = "mbirthday")
private Date mbirthday;
@Type(type = "java.lang.Integer")
@Column(name = "msex", length = 3)
private int msex; // 多对一的属性
@ManyToOne(fetch = FetchType.EAGER,cascade = {CascadeType.MERGE,CascadeType.REFRESH,CascadeType.PERSIST},optional = true)
@JoinColumn(name = "cid")
private Classes classes; public Classes getClasses()
{
return classes;
} public void setClasses(Classes classes)
{
this.classes = classes;
} public int getMid()
{
return mid;
} public void setMid(int mid)
{
this.mid = mid;
} public String getMname()
{
return mname;
} public void setMname(String mname)
{
this.mname = mname;
} public Date getMbirthday()
{
return mbirthday;
} public void setMbirthday(Date mbirthday)
{
this.mbirthday = mbirthday;
} public int getMsex()
{
return msex;
} public void setMsex(int msex)
{
this.msex = msex;
} public int compareTo(Member o)
{
return this.getMname().compareTo(o.getMname());
}}
小弟对CascadeType的级别不是很明白,哪端有cascade = { CascadeType.ALL },哪端的操作就有级联相关的对象,如对班级的增加删除修改更新都会影响到人员,但是如果人员的增加删除修改是不行的.
会报以下的错误:org.hibernate.TransientObjectException:object references an unsaved transient instance - save the transient instance before flushing: com.wang.sprhiber.pojo.Classes但是如果两端都配置上cascade = { CascadeType.ALL },如果要是删除人员的话,不仅会把当前人删除,还把班级以级班级中的其它人删除,这样太可怕了.按照常,操作一的时候,都应该影响到多的一端;但是如果操作多的时候删了删除不影响以外,其它都应该影响.在XML里面就是
多的一端的级联是<cascade = All ,一的一端的级别是:Cascade= save-update.小弟想用注解也实现以上的功能,可不知为什么我配的{CascadeType.MERGE,CascadeType.REFRESH,CascadeType.PERSIST},不起作用.
请高手们帮下帮下小弟吧!!

解决方案 »

  1.   

    用xml看起来都清晰些。楼主换成xml的吧。
      

  2.   

    没有过这种,都用xml
    顶下吧
      

  3.   

    先纠正一下,除了 @Type 之外,其他的都是 JPA 注解,只因为 Hibernate 也是 JPA 的实现之一。我一般是不建议使用级联功能,这样做很可能会产生很多意想不到的效果,级联功能仅仅是减少了
    代码的行数,在效率上没有一点点优势,而且还可能引起不必要的更新。而且你这个关联设得也有问题,在多的一端竟然设成 FetchType.EAGER,也就是在查询 Classes 实
    体时把其中所有的 Member 全部查询出来了!
      

  4.   


    <!-- 多个人对应一个用户 -->
    <many-to-one name="demoUser" column="uid" cascade="save-update"
     class="com.shop.demo.pojo.DemoUser" lazy="false"/> <!-- 一个用户有多篇文章 -->
            <set name="articleSet" inverse="true" cascade="all" lazy="false">
             <key column="uid"/>
             <one-to-many class="com.shop.demo.pojo.DemoArticle"/>
            </set>
    这是小弟做的XML练习.小弟发现,如果不结合Spring中的OpensessionInview的话,不管查询哪端如果想加载
    关联对象,必须取消延迟加载.但是发现在删除的时候删除一的一端正常,(因为cascade="all"),但是在删除多的一端的时候就会出现异常,但是如果加上延迟加载的话,就不会报异常.仿佛cascade="save-update"
    就没有起到作用.
    唉,没有OpensessionInview的话,真是鱼与熊掌不可兼得.
    请高手们给点意见吧!
      

  5.   

    你确定是要双向关联吗? 注解一般写到 get方法上面会更好一些 , 有的时候写在上面不起作用
      

  6.   

    我觉得和加的位置没有关系,我加上Get方法上就报错了.
    为什么我操作多的一端的时候,尤其是删除的话(为了了方便查询,我去掉了延迟加载.),会报错呢?没有Spring中的OpenSessionInview,
    请高手帮忙解决一下我在8楼提的问题吧.
    谢谢!!!
      

  7.   

    听说OpenSessionInview并不是很好 我更建议LZ在FILTER里控制事务
    另外 级联的话我一般只设置delete 别的都不设置 
      

  8.   

    10我提的问题不会是Hibernate的Bug吧
      

  9.   

    首先你用的是jpa的级联机制,jpa的级联机制并不是很完美,有时候甚至和数据库相关,用hibernate的级联机制吧 import org.hibernate.annotations.Cascade; 
    import org.hibernate.annotations.CascadeType;    @ManyToOne(fetch = FetchType.EAGER,cascade = {CascadeType.MERGE,CascadeType.REFRESH,CascadeType.PERSIST},optional = true)
        @JoinColumn(name = "cid")
    改成
       @ManyToOne(fetch = FetchType.EAGER)
    @Cascade(value={CascadeType.SAVE_UPDATE}) 
        @JoinColumn(name = "cid")