Hibernate annotation 多对多 双向关联 问题

zhoubaoyi 2010-02-01 06:28:43


如题,用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;
}

...全文
1052 17 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
nevernam 2010-02-02
  • 打赏
  • 举报
回复
14楼的同学终于说到点子上了
owen_008 2010-02-02
  • 打赏
  • 举报
回复
ecc_report
BearKin 2010-02-02
  • 打赏
  • 举报
回复

//关系集合
@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;
BearKin 2010-02-02
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 zhoubaoyi 的回复:]
回楼上

现在问题是换成Annotation无法实现和hbm的效果

多对多关系以前用hbm完全是不存在问题的。。
[/Quote]

是么..

如果有中间表的话 告诉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;
islandrabbit 2010-02-02
  • 打赏
  • 举报
回复
看了楼主的配置有几点想法。

首先楼主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"。

lp19890601 2010-02-01
  • 打赏
  • 举报
回复
其他的表不管,只要关联中间表,不管其他表的事
xujun614 2010-02-01
  • 打赏
  • 举报
回复
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;
}
}
可以搞定的
crazylaa 2010-02-01
  • 打赏
  • 举报
回复
路过
zhoubaoyi 2010-02-01
  • 打赏
  • 举报
回复
回楼主

试了啊,还是 插入数据的时候,只写其中一张
zhj92lxs 2010-02-01
  • 打赏
  • 举报
回复
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照着改下吧
fjhooo 2010-02-01
  • 打赏
  • 举报
回复
我也遇到这样的问题,jpa 的 annotation 没办法 实现跟 hbm配置文件 多对多的效果 给我造成了很大的困扰
希望大家进行有意义的 讨论 不是粘贴一大段东西来
zhoubaoyi 2010-02-01
  • 打赏
  • 举报
回复
回楼上

现在问题是换成Annotation无法实现和hbm的效果

多对多关系以前用hbm完全是不存在问题的。。
lp19890601 2010-02-01
  • 打赏
  • 举报
回复
多对多需要一个中间表来确定其关系的维护权

中间表只需要连个字段,即两张表的关系,也可以是主外键,

映射时无须映射中间表:

只需映射需要的两张表即可两张表

关键是里面的配置
//部门表
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>


中间表只有 部门表的主键和职位表的主键,他们就是靠中间表来围护对方的

希望可以对你有所帮助!
蛋黄车 2010-02-01
  • 打赏
  • 举报
回复
强烈不建议使用多对多关联关系!!
coveking 2010-02-01
  • 打赏
  • 举报
回复
帮顶下。
islandrabbit 2010-02-01
  • 打赏
  • 举报
回复
下班回家看看!
nevernam 2010-02-01
  • 打赏
  • 举报
回复
强烈关注,我也遇到了这个问题

67,549

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧