如题,用HBM的时候可以按照我们的需求完成双向关联的CRUD,但是现在项目需求用Annotation,结果总是无法实现跟使用hbm时候的效果--具体表现为用annotation的时候,如果不写mappedby,则生成2张维护关系用的表,而每次在一端插入数据的时候,只写其中一张,那么需要在另外一端重新维护的时候,调用的却是另外一张关系表,这样就无法达到目的总之,重点是要用annotation实现多对多的双向关联举例代码如下:使用hbm时候的.xml文件:1.Student端:
    <class name="com.bjsxt.hibernate.Student" table="student" schema="a">
    <id name="id"  type="integer">
    <generator class="native"></generator>
    </id>
   <property name="name"  type="string"></property>
  
   <set name="teachers" table="teacher_student" cascade="all">
<key column="students_id"></key>
<many-to-many class="com.bjsxt.hibernate.Teacher" column="teachers_id"></many-to-many>
</set>
    </class>
2.Teacher端<hibernate-mapping>
<class name="com.bjsxt.hibernate.Teacher" table="teacher" schema="a">
<id name="id" type="integer">
<generator class="native"></generator>
</id>
<property name="name" type="string"></property> <set name="students" table="teacher_student" cascade="all">
<key column="teachers_id"></key>
<many-to-many class="com.bjsxt.hibernate.Student"
column="students_id" />
</set>
</class>
</hibernate-mapping>
然后是annotation部分的关键部分:1.student端@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "students", targetEntity = Teacher.class)

public Set<Teacher> getTeachers() {
return this.teachers;
}2.teacher端@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinTable(name = "teacher_student", catalog = "a", joinColumns = { @JoinColumn(name = "teachers_id", nullable = false, updatable = false) }, inverseJoinColumns = { @JoinColumn(name = "students_id", nullable = false, updatable = false) })
public Set<Student> getStudents() {
return this.students;
}

解决方案 »

  1.   

    多对多需要一个中间表来确定其关系的维护权中间表只需要连个字段,即两张表的关系,也可以是主外键,映射时无须映射中间表:只需映射需要的两张表即可两张表关键是里面的配置
    //部门表
    package pojo;import java.util.HashSet;
    import java.util.Set;/**
     * Department generated by MyEclipse Persistence Tools
     */public class Department implements java.io.Serializable { // Fields private Integer oid; private Integer parentoid; private String deptName; private String phone; private String email; private String fax; private Integer manager; private String address; private String zipcode; private String description; private Integer[] jobids; private Set<Job> jobs = new HashSet<Job>(0);//职位集合 private Set<Employee> emps = new HashSet<Employee>(0);//员工集合 // Constructors public Integer[] getJobids() {
    return jobids;
    } public void setJobids(Integer[] jobids) {
    this.jobids = jobids;
    } public Set<Job> getJobs() {
    return jobs;
    } public void setJobs(Set<Job> jobs) {
    this.jobs = jobs;
    } // Property accessors public Integer getOid() {
    return this.oid;
    } public void setOid(Integer oid) {
    this.oid = oid;
    } public Integer getParentoid() {
    return this.parentoid;
    } public void setParentoid(Integer parentoid) {
    this.parentoid = parentoid;
    } public String getDeptName() {
    return this.deptName;
    } public void setDeptName(String deptName) {
    this.deptName = deptName;
    } public String getPhone() {
    return this.phone;
    } public void setPhone(String phone) {
    this.phone = phone;
    } public String getEmail() {
    return this.email;
    } public void setEmail(String email) {
    this.email = email;
    } public String getFax() {
    return this.fax;
    } public void setFax(String fax) {
    this.fax = fax;
    } public Integer getManager() {
    return this.manager;
    } public void setManager(Integer manager) {
    this.manager = manager;
    } public String getAddress() {
    return this.address;
    } public void setAddress(String address) {
    this.address = address;
    } public String getZipcode() {
    return this.zipcode;
    } public void setZipcode(String zipcode) {
    this.zipcode = zipcode;
    } public String getDescription() {
    return this.description;
    } public void setDescription(String description) {
    this.description = description;
    } public Set<Employee> getEmps() {
    return emps;
    } public void setEmps(Set<Employee> emps) {
    this.emps = emps;
    }}
    //职位表package pojo;import java.util.HashSet;
    import java.util.Set;/**
     * Job generated by MyEclipse Persistence Tools
     */public class Job implements java.io.Serializable { // Fields private Integer oid; private String jobname; private Set<Department> depts = new HashSet<Department>(0); // Constructors /** default constructor */
    public Job() {
    } /** full constructor */
    public Job(String jobname) {
    this.jobname = jobname;
    } // Property accessors public Integer getOid() {
    return this.oid;
    } public void setOid(Integer oid) {
    this.oid = oid;
    } public String getJobname() {
    return this.jobname;
    } public void setJobname(String jobname) {
    this.jobname = jobname;
    } public Set<Department> getDepts() {
    return depts;
    } public void setDepts(Set<Department> depts) {
    this.depts = depts;
    }}
    //部门表映射文件及配置
    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <!-- 
    Mapping file autogenerated by MyEclipse Persistence Tools
    -->
    <hibernate-mapping>
    <class name="pojo.Department" table="Department" schema="dbo"
    catalog="study">
    <id name="oid" type="java.lang.Integer">
    <column name="oid" />
    <generator class="native" />
    </id>
    <property name="parentoid" type="java.lang.Integer">
    <column name="parentoid" />
    </property>
    <property name="deptName" type="java.lang.String">
    <column name="deptName" length="20" />
    </property>
    <property name="phone" type="java.lang.String">
    <column name="phone" length="20" />
    </property>
    <property name="email" type="java.lang.String">
    <column name="email" length="100" />
    </property>
    <property name="fax" type="java.lang.String">
    <column name="fax" length="20" />
    </property>
    <property name="manager" type="java.lang.Integer">
    <column name="manager" />
    </property>
    <property name="address" type="java.lang.String">
    <column name="address" length="100" />
    </property>
    <property name="zipcode" type="java.lang.String">
    <column name="zipcode" length="10" />
    </property>
    <property name="description" type="java.lang.String">
    <column name="description" length="100" />
    </property>
                                       <!-- 中间表 -->
    <set name="jobs" table="department_job"><!-- 职位集合配置 -->
                            <!-- 中间表对应的部门字段 -->
    <key column="deptid"></key>
                                                <!-- 中间表对应的职位字段 -->
    <many-to-many class="pojo.Job" column="jobid">
    </many-to-many>
    </set>
    <set name="emps" cascade="all" inverse="false"><!-- 员工集合配置 --> <key column="deptid"></key>
    <one-to-many class="pojo.Employee" />
    </set>
    </class>
    </hibernate-mapping>
    //职位表映射及配置<?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <!-- 
    Mapping file autogenerated by MyEclipse Persistence Tools
    -->
    <hibernate-mapping>
    <class name="pojo.Job" table="job" schema="dbo" catalog="study">
    <id name="oid" type="java.lang.Integer">
    <column name="oid" />
    <generator class="native" />
    </id>
    <property name="jobname" type="java.lang.String">
    <column name="jobname" length="50" />
    </property>
                                          <!-- 中间表 -->
    <set name="depts" table="department_job">
                            <!-- 中间表对应的职位字段 -->
    <key column="jobid"></key>
                             <!-- 中间表对应的部门字段 -->
    <many-to-many class="pojo.Department" column="deptid"></many-to-many>
    </set>
    </class>
    </hibernate-mapping>
    中间表只有 部门表的主键和职位表的主键,他们就是靠中间表来围护对方的希望可以对你有所帮助!
      

  2.   

    回楼上现在问题是换成Annotation无法实现和hbm的效果多对多关系以前用hbm完全是不存在问题的。。
      

  3.   

    我也遇到这样的问题,jpa 的 annotation 没办法 实现跟 hbm配置文件 多对多的效果 给我造成了很大的困扰 
    希望大家进行有意义的 讨论 不是粘贴一大段东西来 
      

  4.   

    import java.util.HashSet;
    import java.util.Set;import javax.persistence.CascadeType;
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.FetchType;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.JoinColumn;
    import javax.persistence.JoinTable;
    import javax.persistence.ManyToMany;@Entity
    public class Student {
    private Integer id;
    private String name;

    private Set<Teacher> teachers = new HashSet<Teacher>();

    public Student(){}

    public Student(String name) {
    this.name = name;
    }
    @Id @GeneratedValue
    public Integer getId() {
    return id;
    }
    public void setId(Integer id) {
    this.id = id;
    }

    @Column(length=10,nullable=false)
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }

    @ManyToMany(cascade=CascadeType.REFRESH,fetch=FetchType.LAZY)
    @JoinTable(name="student_teacher",
    inverseJoinColumns=@JoinColumn(name="teacher_id"),
    joinColumns=@JoinColumn(name="student_id"))

    public Set<Teacher> getTeachers() {
    return teachers;
    }
    public void setTeachers(Set<Teacher> teachers) {
    this.teachers = teachers;
    }

    public void addTeacher(Teacher teacher){
    this.teachers.add(teacher);
    }

    public void remoceTeacher(Teacher teacher){
    if(this.teachers.contains(teacher))
    this.teachers.remove(teacher);
    }
    }import java.util.HashSet;
    import java.util.Set;import javax.persistence.CascadeType;
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.FetchType;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.ManyToMany;@Entity
    public class Teacher {
    private Integer id;
    private String name; private Set<Student> students = new HashSet<Student>();

    public Teacher(){}

    public Teacher(String name) {
    this.name = name;
    } @Id
    @GeneratedValue
    public Integer getId() {
    return id;
    } public void setId(Integer id) {
    this.id = id;
    } @Column(length = 10, nullable = false)
    public String getName() {
    return name;
    } public void setName(String name) {
    this.name = name;
    }


    @ManyToMany(cascade = CascadeType.REFRESH, fetch = FetchType.LAZY, mappedBy = "teachers")
    public Set<Student> getStudents() {
    return students;
    } public void setStudents(Set<Student> students) {
    this.students = students;
    } @Override
    public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((id == null) ? 0 : id.hashCode());
    return result;
    } @Override
    public boolean equals(Object obj) {
    if (this == obj)
    return true;
    if (obj == null)
    return false;
    if (getClass() != obj.getClass())
    return false;
    Teacher other = (Teacher) obj;
    if (id == null) {
    if (other.id != null)
    return false;
    } else if (!id.equals(other.id))
    return false;
    return true;
    }


    }
    给你个例子,这是jpa实现的,hibernate照着改下吧
      

  5.   

    public class Student {
    private int id;
    private String name;
    private Set<Teacher> teachers = new HashSet<Teacher>();
    @ManyToMany(mappedBy="students")
    public Set<Teacher> getTeachers() {
    return teachers;
    }
    public void setTeachers(Set<Teacher> teachers) {
    this.teachers = teachers;
    }
    @Id
    @GeneratedValue
    public int getId() {
    return id;
    }
    public void setId(int id) {
    this.id = id;
    }
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    }
    @Entity
    public class Teacher {
    private int id;
    private String name;
    private Set<Student> students = new HashSet<Student>();
    @Id
    @GeneratedValue
    public int getId() {
    return id;
    }
    public void setId(int id) {
    this.id = id;
    }
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    @ManyToMany
    @JoinTable(name="t_s",
    joinColumns={@JoinColumn(name="teacher_id")},
    inverseJoinColumns={@JoinColumn(name="student_id")}
    )
    public Set<Student> getStudents() {
    return students;
    }
    public void setStudents(Set<Student> students) {
    this.students = students;
    }
    }
    可以搞定的
      

  6.   

    看了楼主的配置有几点想法。首先楼主xml映射的配置至少有两点问题:1. 缺少inverse="true"。因为楼主配的是个双向多对多,必须在配置中决定关系的哪一边来更新中间表。2. 楼主使用了cascade="all", 这个对于多对多来说也是不行的。cascade="save-update"是可以的。
       cascade="all"就包含了cascade="delete"。试想一下你删除A就会删除A下面所有的B,但因为是多对多这个A下面的B还可能对应着其他的A。楼主说如果不写mappedby,则生成2张维护关系用的表。那个mappedby不写是不行的,它相当于xml里的inverse="true"。
      

  7.   


    是么..如果有中间表的话 告诉LZ怎么弄
    //关系集合
    @ManyToMany(targetEntity=Student.class)
    @JoinTable(name="STUDENT_SUBJECT",
    joinColumns=@JoinColumn(name="SUBJECT_ID",referencedColumnName="ID"),
    inverseJoinColumns=@JoinColumn(name="STUDENT_ID",referencedColumnName="ID"))
    private Set students;
    //关系集合
    @ManyToMany(targetEntity=Student.class)
    @JoinTable(name="STUDENT_SUBJECT",
    joinColumns=@JoinColumn(name="SUBJECT_ID",referencedColumnName="ID"),
    inverseJoinColumns=@JoinColumn(name="STUDENT_ID",referencedColumnName="ID"))
    private Set students;
      

  8.   


    //关系集合
    @ManyToMany(targetEntity=Subject.class)
    @JoinTable(name="STUDENT_SUBJECT",
    joinColumns=@JoinColumn(name="STUDENT_ID",referencedColumnName="ID"),
    inverseJoinColumns=@JoinColumn(name="SUBJECT_ID",referencedColumnName="ID"))
    private Set subjects;