关于延迟加载:
http://blog.csdn.net/z69183787/article/details/20049409
http://blog.csdn.net/z69183787/article/details/17136627
http://blog.csdn.net/z69183787/article/details/8197106
http://blog.csdn.net/z69183787/article/details/18615577
关系类型总结和对应的注解
1. Hibernate Annotation关系映射有下面几种类型:
1)一对一外键关联映射(单向)
2)一对一外键关联映射(双向)
3)一对一主键关联映射(不重要)在这不演示
在实际中很少用,使用注解@PrimaryKeyJoinColumn
意思是说,我的主键去参考另外一张表中的主键,作为我的主键,但是在我测试使用
注解一对一主键关联映射,在生成表的时候,数据库中并没有生成关联,使用XML
映射可以生成。Annotation注解一对一主键关联映,有些bug。不过没空去研究它。
因为在实际开发中一对一很少用。在实际开发中我机会没有用过,主键关联就更少了
4)多对一关联映射
5)一对多关联映射(单向)
6)一对多关联映射(双向)
7)多对多关联映射(单向)
8)多对多关联映射(双向)
2.介绍各种映射用法
1)一对一外键关联映射(单向)
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name="userid",unique=true)
//一对一外键关联,使用@OneToOne,并设置了级联操作
//@JoinColum设置了外键的名称为userid(数据库字段名),如果不设置,则默认为另一类的属性名+ _id
//外键的值是唯一的(unique),不可重复,与另一类的主键一直
2)一对一外键关联映射(双向)
Class1里与上面一样,
Class2:
@OneToOne(mappedBy="class2",cascade=CascadeType.ALL)
//一对一双向关联关系,使用@OneToOne
//注意:需要加上mappedBy="class2",如果不加上的话,
//Class2也会生成一个外键(class1_id)
//mappedby="class2"需要指向与他关联对象的一个属性
//说明双向关联关系中,有且仅有一端是作为主体(owner)端存在的
//主体端负责维护联接列
//对于不需要维护这种关系的从表则通过mappedBy属性进行声明
//mappedBy的值指向主体的关联属性
//规律:只有是双向关联关系,都加上mappedby
//cascade=CascadeType.ALL级联
4)多对一关联映射
在多的一端配置:
@ManyToOne(targetEntity=Organization.class)
@JoinColumn(name="orgid")
//多对一注解@ManyToOne
//targetEntity指定了关联对象
//@JoinColumn(name="orgid")指定生产的外键的字段名,默认是org_id
5)一对多关联映射(单向)
@OneToMany
@JoinColumn(name="orgid")
/**
* 一对多注解@OneToMany(单向)
* 如果只写@OneToMany的话,hibernate会建一张中间表来
* 维护他们之间的关系,
* 加上@JoinColumn(name="orgid"),则不会建中间表,他会在
* 多的一端加上外键orgid,来维护他们之间的关系
*/
6)一对多关联映射(双向)
一端:
@OneToMany(mappedBy="org")
@JoinColumn(name="orgid")
/**
* 一对多双向,在一的一端中设置mappedBy
* 说明多的一端为主导
* 如果指定了外键字段名称,则多的一端也需要指定相同的字段名称
*/
多端:
@ManyToOne
@JoinColumn(name="orgid")
/**
* 一对多双向
* 需要指定外键与一的一端给的外键名称一致,@JoinColumn(name="orgid")
* 也可以不指定,如果在多的一端不指定,则一的一端也不能指定
* 否则为生成两个外键
*/
7)多对多关联映射(单向)
@ManyToMany
/**
* 多对多映射:注解@ManyToMany(单向)
* 默认情况下,hibernate会自动的创建一张中间表,
* 来维护多对多关系
* 默认中间表的名称 :user_role中间表,字段的名称user_id role_id
* 如果想更换表名和字段名称,注解如下:
*/
@JoinTable(name="t_u_r",
joinColumns={@JoinColumn(name="u_id")},
inverseJoinColumns={@JoinColumn(name="r_id")}
)
8)多对多关联映射(双向) User端
@ManyToMany
/**
* 多对多映射:注解@ManyToMany(单向)
* 默认情况下,hibernate会自动的创建一张中间表,
* 来维护多对多关系
* 默认中间表的名称 :user_role中间表,字段的名称user_id role_id
* 如果想更换表名和字段名称,注解如下:
*/
@JoinTable(name="t_u_r",
joinColumns={@JoinColumn(name="u_id")},
inverseJoinColumns={@JoinColumn(name="r_id")}
)
/**
* @JoinTable(name="t_u_r",
* 指定中间表的表名
* joinColumns={@JoinColumn(name="u_id")},
* 指定当前对象的外键
* inverseJoinColumns={@JoinColumn(name="r_id")}
* 指定关联对象的外键
*/
Role端
@ManyToMany(mappedBy="role")
/**
* 多对多,双向关联映射
*/
1.多对多 -- 基于ACL的权限控制数据库设计3+2
/*
Navicat MySQL Data Transfer
Source Server : mysql
Source Server Version : 50527
Source Host : localhost:3306
Source Database : shiro
Target Server Type : MYSQL
Target Server Version : 50527
File Encoding : 65001
Date: 2014-08-20 17:13:20
*/
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `tbl_permission`
-- ----------------------------
DROP TABLE IF EXISTS `tbl_permission`;
CREATE TABLE `tbl_permission` (
`PERMISSION_ID` int(11) NOT NULL AUTO_INCREMENT,
`PERMISSION_NAME` varchar(45) DEFAULT NULL,
`createdTime` datetime DEFAULT NULL,
`lastVisitTime` datetime DEFAULT NULL,
`status` int(11) NOT NULL,
`role` tinyblob,
PRIMARY KEY (`PERMISSION_ID`),
UNIQUE KEY `PERMISSION_NAME_UNIQUE` (`PERMISSION_NAME`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of tbl_permission
-- ----------------------------
INSERT INTO `tbl_permission` VALUES ('1', 'see', null, null, '0', null);
INSERT INTO `tbl_permission` VALUES ('2', 'check', null, null, '0', null);
INSERT INTO `tbl_permission` VALUES ('3', 'add', null, null, '0', null);
INSERT INTO `tbl_permission` VALUES ('4', 'delete', null, null, '0', null);
-- ----------------------------
-- Table structure for `tbl_permission_role`
-- ----------------------------
DROP TABLE IF EXISTS `tbl_permission_role`;
CREATE TABLE `tbl_permission_role` (
`ROLE_ID` int(11) NOT NULL,
`PERMISSION_ID` int(11) NOT NULL,
PRIMARY KEY (`ROLE_ID`,`PERMISSION_ID`),
KEY `FKCD309665B1C23A26` (`ROLE_ID`),
KEY `FKCD3096659AEFBE86` (`PERMISSION_ID`),
CONSTRAINT `FKCD3096659AEFBE86` FOREIGN KEY (`PERMISSION_ID`) REFERENCES `tbl_permission` (`PERMISSION_ID`),
CONSTRAINT `FKCD309665B1C23A26` FOREIGN KEY (`ROLE_ID`) REFERENCES `tbl_role` (`ROLE_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of tbl_permission_role
-- ----------------------------
INSERT INTO `tbl_permission_role` VALUES ('1', '1');
INSERT INTO `tbl_permission_role` VALUES ('1', '2');
INSERT INTO `tbl_permission_role` VALUES ('1', '3');
INSERT INTO `tbl_permission_role` VALUES ('2', '4');
-- ----------------------------
-- Table structure for `tbl_role`
-- ----------------------------
DROP TABLE IF EXISTS `tbl_role`;
CREATE TABLE `tbl_role` (
`ROLE_ID` int(11) NOT NULL AUTO_INCREMENT,
`ROLE_NAME` varchar(45) DEFAULT NULL,
`createdTime` datetime DEFAULT NULL,
`lastVisitTime` datetime DEFAULT NULL,
`status` int(11) NOT NULL,
`user_id` varchar(255) NOT NULL,
PRIMARY KEY (`ROLE_ID`),
UNIQUE KEY `ROLE_NAME_UNIQUE` (`ROLE_NAME`),
KEY `FKFE6A057B1C23A26` (`ROLE_ID`),
CONSTRAINT `FKFE6A057B1C23A26` FOREIGN KEY (`ROLE_ID`) REFERENCES `tbl_role` (`ROLE_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of tbl_role
-- ----------------------------
INSERT INTO `tbl_role` VALUES ('1', 'admin', null, null, '0', '');
INSERT INTO `tbl_role` VALUES ('2', 'manager', null, null, '0', '');
INSERT INTO `tbl_role` VALUES ('3', 'employee', null, null, '0', '');
INSERT INTO `tbl_role` VALUES ('4', 'clerk', null, null, '0', '');
-- ----------------------------
-- Table structure for `tbl_role_user`
-- ----------------------------
DROP TABLE IF EXISTS `tbl_role_user`;
CREATE TABLE `tbl_role_user` (
`ROLE_ID` int(11) NOT NULL,
`USER_ID` int(11) NOT NULL,
`tbl_role_role_id` int(11) NOT NULL,
`userSet_user_id` varchar(255) NOT NULL,
PRIMARY KEY (`ROLE_ID`,`USER_ID`),
KEY `FK9124A2B3B1C23A26` (`ROLE_ID`),
KEY `FK9124A2B356ECFE06` (`USER_ID`),
CONSTRAINT `FK9124A2B356ECFE06` FOREIGN KEY (`USER_ID`) REFERENCES `tbl_user` (`USER_ID`),
CONSTRAINT `FK9124A2B3B1C23A26` FOREIGN KEY (`ROLE_ID`) REFERENCES `tbl_role` (`ROLE_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of tbl_role_user
-- ----------------------------
INSERT INTO `tbl_role_user` VALUES ('1', '1', '0', '');
INSERT INTO `tbl_role_user` VALUES ('2', '1', '0', '');
INSERT INTO `tbl_role_user` VALUES ('3', '1', '0', '');
-- ----------------------------
-- Table structure for `tbl_user`
-- ----------------------------
DROP TABLE IF EXISTS `tbl_user`;
CREATE TABLE `tbl_user` (
`USER_ID` int(11) NOT NULL AUTO_INCREMENT,
`USER_USERNAME` varchar(45) NOT NULL,
`USER_PASSWORD` char(32) NOT NULL,
PRIMARY KEY (`USER_ID`),
UNIQUE KEY `USER_USERNAME_UNIQUE` (`USER_USERNAME`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of tbl_user
-- ----------------------------
INSERT INTO `tbl_user` VALUES ('1', 'aa', 'aa');
package com.jay.demo.bean;
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;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
/**
* 使用Hibernate的注解方式配置映射关系
* @author He
*
*/
/*@Entity 注解将一个类声明为实体 Bean, @Id 注解声明了该实体Bean的标识属性。
*
* 当前类是一个持久化类User,映射的表示User,所对应的数据库时shiro
* name --- 表名
* catelog --- 数据库名
* 这句:@Table(catalog="shiro",name="tbl_user") 可以省略
*/
@Entity
@Table(catalog="shiro",name="tbl_user")
public class User extends BaseModel{
private String id;
private String username;
private String password;
private Set<Role> roleSet = new HashSet<Role>();
public User() {
}
// 主键 :@Id 主键生成方式:strategy = "increment"
//映射表中id这个字段,不能为空,并且是唯一的
@Id
@GenericGenerator(name="generator",strategy="increment")
@GeneratedValue(generator="generator")
@Column(name="user_id",unique=true, nullable=false)
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Column(name="user_username")
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Column(name="user_password")
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@ManyToMany(cascade={CascadeType.MERGE,CascadeType.PERSIST},
targetEntity=com.jay.demo.bean.Role.class,
fetch=FetchType.EAGER)
@JoinTable(
name="tbl_role_user",
joinColumns={@JoinColumn(name="user_id")},
inverseJoinColumns={@JoinColumn(name="role_id")}
)
public Set<Role> getRoleSet() {
return roleSet;
}
public void setRoleSet(Set<Role> roleSet) {
this.roleSet = roleSet;
}
}
package com.jay.demo.bean;
import java.io.Serializable;
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.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(catalog="shiro",name="tbl_role")
public class Role extends BaseModel implements Serializable {
private static final long serialVersionUID = -4987248128309954399L;
private Integer id;
private String name;
private Set<User> userSet = new HashSet<User>();
private Set<Permission> permissionSet = new HashSet<Permission>();
public Role() {
super();
}
// --------------------------------------------------------------------------------
@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;
Role other = (Role) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
// --------------------------------------------------------------------------------
@Id
@Column(name="role_id")
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Column(name="role_name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@ManyToMany(cascade={CascadeType.MERGE,CascadeType.PERSIST},
targetEntity=com.jay.demo.bean.Permission.class,
fetch=FetchType.EAGER)
@JoinTable(
name="tbl_permission_role",
joinColumns={@JoinColumn(name="role_id")},
inverseJoinColumns={@JoinColumn(name="permission_id")}
)
public Set<Permission> getPermissionSet() {
return permissionSet;
}
public void setPermissionSet(Set<Permission> permissionSet) {
this.permissionSet = permissionSet;
}
@ManyToMany(cascade={CascadeType.MERGE,CascadeType.PERSIST},
// mappedBy="roleSet",
targetEntity=com.jay.demo.bean.User.class)
public Set<User> getUserSet() {
return userSet;
}
public void setUserSet(Set<User> userSet) {
this.userSet = userSet;
}
}
package com.jay.demo.bean;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import com.jay.demo.bean.Role;
@Entity
@Table(catalog="shiro",name="tbl_permission")
public class Permission extends BaseModel implements Serializable {
private static final long serialVersionUID = -8025597823572680802L;
private Integer id;
private String name;
private Role role;
public Permission() {
super();
}
// --------------------------------------------------------------------------------------
@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;
Permission other = (Permission) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
// --------------------------------------------------------------------------------------
@Id
@Column(name="Permission_id")
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Column(name="Permission_name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
}
2.一对多和多对一关系映射注解版
package com.jay.demo.bean;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(catalog="shiro",name="tbl_category")
public class Category extends BaseModel implements Serializable{
private static final long serialVersionUID = 1812600303779451508L;
private String id;
private String categoryName;
private Set<Product> products = new HashSet<Product>();
public Category() {
super();
}
@Id
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getCategoryName() {
return categoryName;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
@OneToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY,mappedBy="category")
public Set<Product> getProducts() {
return products;
}
public void setProducts(Set<Product> products) {
this.products = products;
}
}
package com.jay.demo.bean;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(catalog="shiro",name="tbl_product")
public class Product extends BaseModel implements Serializable{
private static final long serialVersionUID = -7663728419648348545L;
private String id;
private String productName;
private String price;
private Category category;
private Date inDate;
private long count;
@Id
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
@ManyToOne
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
public Date getInDate() {
return inDate;
}
public void setInDate(Date inDate) {
this.inDate = inDate;
}
public long getCount() {
return count;
}
public void setCount(long count) {
this.count = count;
}
public Product() {
super();
}
}
一对多注解版的例子
首先是在hibernate.cfg.xml中引入要映射的class
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=GBK</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">sa</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<mapping class="com.sszd.hibernate.Reader"/>
<mapping class="com.sszd.hibernate.Book"/>
</session-factory>
</hibernate-configuration>
我们分别看看reader.java和book.java文件
Reader.java
package com.sszd.hibernate;
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.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name="reader")
public class Reader {
@Id
@Column(name="ID")
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
@Column(name="MENO")
private String meno;
@Column(name="NAME")
private String name;
@OneToMany(mappedBy = "reader", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<Book> books = new HashSet<Book>();
public Reader()
{
}
public Set getBooks() {
return books;
}
public void setBooks(Set books) {
this.books = books;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getMeno() {
return meno;
}
public void setMeno(String meno) {
this.meno = meno;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
book.java
package com.sszd.hibernate;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name="book")
public class Book {
@Id
@Column(name="ID")
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
@Column(name="TITLE")
private String title;
@ManyToOne(cascade = CascadeType.ALL, optional = false)
@JoinColumn(name="rea_id", referencedColumnName="id")//外键为sut_id,与student中的id关联
private Reader reader;
public int getId() {
return id;
}
public Reader getReader() {
return reader;
}
public void setReader(Reader reader) {
this.reader = reader;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
接下来是我们的本地测试用例
package com.sszd.main;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.AnnotationConfiguration;
import com.sszd.hibernate.Book;
import com.sszd.hibernate.Reader;
public class ReaderToBooks {
private static SessionFactory sessionFactory;
public static void main(String[] args) {
sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
Reader r = new Reader();
r.setName("Reader zhang");
Book b1 = new Book();
b1.setTitle("title1");
Book b2 = new Book();
b2.setTitle("title2");
b1.setReader(r);
b2.setReader(r);
r.getBooks().add(b1);
r.getBooks().add(b2);
Transaction trx = session.beginTransaction();
session.save(r);
trx.commit();
session.close();
}
}
一对多实例二
student:
- /**
- *
- */
- package com.wonders.task.sample.bo;
- import javax.persistence.CascadeType;
- import javax.persistence.Column;
- import javax.persistence.Entity;
- import javax.persistence.GeneratedValue;
- import javax.persistence.Id;
- import javax.persistence.JoinColumn;
- import javax.persistence.ManyToOne;
- import javax.persistence.Table;
- import org.hibernate.annotations.GenericGenerator;
- /**
- * @ClassName: Student
- * @Description: TODO(这里用一句话描述这个类的作用)
- * @author zhoushun
- * @date 2014年2月27日 上午11:48:30
- *
- */
- @Entity
- @Table(name="Z_STUDENT")
- public class Student {
- private String id;
- private String name;
- private Clazz clazz;
- @Id
- @GeneratedValue(generator="system-uuid")
- @GenericGenerator(name="system-uuid", strategy = "uuid")
- @Column(name = "ID")
- public String getId() {
- return id;
- }
- public void setId(String id) {
- this.id = id;
- }
- @Column(name = "NAME", length = 500)
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- @ManyToOne(cascade={CascadeType.ALL})
- @JoinColumn(name="class_id") //student类中对应外键的属性:classid
- public Clazz getClazz() {
- return clazz;
- }
- public void setClazz(Clazz clazz) {
- this.clazz = clazz;
- }
- }
classes:
- /**
- *
- */
- package com.wonders.task.sample.bo;
- import java.util.Set;
- import javax.persistence.CascadeType;
- import javax.persistence.Column;
- import javax.persistence.Entity;
- import javax.persistence.GeneratedValue;
- import javax.persistence.Id;
- import javax.persistence.OneToMany;
- import javax.persistence.Table;
- import org.hibernate.annotations.GenericGenerator;
- /**
- * @ClassName: Clazz
- * @Description: TODO(这里用一句话描述这个类的作用)
- * @author zhoushun
- * @date 2014年2月27日 上午11:48:47
- *
- */
- @Entity
- @Table(name="Z_CLASS")
- public class Clazz implements java.io.Serializable{
- /**
- *
- */
- private static final long serialVersionUID = -6224738252966513441L;
- private String id;
- private String name;
- private Set<Student> set;
- @Id
- @GeneratedValue(generator="system-uuid")
- @GenericGenerator(name="system-uuid", strategy = "uuid")
- @Column(name = "ID")
- public String getId() {
- return id;
- }
- public void setId(String id) {
- this.id = id;
- }
- @Column(name = "NAME", length = 500)
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- @OneToMany(cascade=CascadeType.ALL,mappedBy="clazz")
- //@OneToMany(cascade=CascadeType.ALL,mappedBy="clazz",fetch=FetchType.EAGER) 关闭延迟加载。
- public Set<Student> getSet() {
- return set;
- }
- public void setSet(Set<Student> set) {
- this.set = set;
- }
- }
- /**
- *
- */
- package com.wonders.task.sample.main;
- import java.util.HashSet;
- import java.util.Set;
- import javax.annotation.Resource;
- import org.hibernate.Hibernate;
- import org.hibernate.Session;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.annotation.Scope;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- import org.springframework.orm.hibernate3.HibernateTemplate;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Propagation;
- import org.springframework.transaction.annotation.Transactional;
- import com.wonders.schedule.util.SpringBeanUtil;
- import com.wonders.task.sample.ITaskService;
- import com.wonders.task.sample.bo.Clazz;
- import com.wonders.task.sample.bo.Student;
- /**
- * @ClassName: TestMain
- * @Description: TODO(这里用一句话描述这个类的作用)
- * @author zhoushun
- * @date 2014年2月27日 下午12:18:44
- *
- */
- @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
- /* 功能模块入口点,beanid即数据库配置中的name */
- @Service("testMain")
- @Scope("prototype")
- public class TestMain {
- private HibernateTemplate hibernateTemplate;
- public HibernateTemplate getHibernateTemplate() {
- return hibernateTemplate;
- }
- //注入hibernateTemplate
- @Resource(name="hibernateTemplate")
- public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
- this.hibernateTemplate = hibernateTemplate;
- }
- public void test(){
- Session session = this.getHibernateTemplate().getSessionFactory().getCurrentSession();
- Clazz c2 = (Clazz) session.get(Clazz.class, "8a81a97c4471c661014471c669360002");
- //Clazz c2 = (Clazz) main.getHibernateTemplate().get(Clazz.class, "8a81a97c4471c661014471c669360002");
- Hibernate.initialize(c2.getSet());
- System.out.println("11111111111111111111111");
- //session.close();
- Set<Student> sss = c2.getSet();
- System.out.println("22222222222222222");
- for(Student s: sss){
- System.out.println(s.getName());
- }
- }
- public static void main(String[] args){
- ApplicationContext applicationContext = null;
- String[] fileUrl = new String[]{"classpath*:applicationContext*.xml"};
- applicationContext = new ClassPathXmlApplicationContext(fileUrl);
- Student s1 = new Student();
- Student s2 = new Student();
- Clazz c1 = new Clazz();
- c1.setName("1班");
- s1.setName("z1");
- s1.setClazz(c1);
- s2.setName("z2");
- s2.setClazz(c1);
- Set<Student> set = new HashSet<Student>();
- set.add(s1);set.add(s2);
- c1.setSet(set);
- TestMain main = (TestMain)SpringBeanUtil.getBean("testMain");
- //main.getHibernateTemplate().save(c1);
- // Session session = main.getHibernateTemplate().getSessionFactory().openSession();
- // Clazz c2 = (Clazz) session.get(Clazz.class, "8a81a97c4471c661014471c669360002");
- // //Clazz c2 = (Clazz) main.getHibernateTemplate().get(Clazz.class, "8a81a97c4471c661014471c669360002");
- // Hibernate.initialize(c2.getSet());
- //
- // System.out.println("11111111111111111111111");
- // session.close();
- // Set<Student> sss = c2.getSet();
- // System.out.println("22222222222222222");
- // for(Student s: sss){
- //
- // System.out.println(s.getName());
- // }
- main.test();
- //main.getHibernateTemplate().delete(c2);
- }
- }
级联保存
方法1:自动维护两表关系,mappedby 为被拥维护方,即对应的student为维护方
- Student s1 = new Student();
- Student s2 = new Student();
- Clazz c1 = new Clazz();
- c1.setName("1班");
- s1.setName("z1");
- s1.setClazz(c1);
- s2.setName("z2");
- s2.setClazz(c1);
- TestMain main = (TestMain)SpringBeanUtil.getBean("testMain");
- main.getHibernateTemplate().save(s1);
- main.getHibernateTemplate().save(s2);
- Student s1 = new Student();
- Student s2 = new Student();
- Clazz c1 = new Clazz();
- c1.setName("1班");
- s1.setName("z1");
- s1.setClazz(c1);
- s2.setName("z2");
- s2.setClazz(c1);
- Set<Student> set = new HashSet<Student>();
- set.add(s1);set.add(s2);
- c1.setSet(set);
- TestMain main = (TestMain)SpringBeanUtil.getBean("testMain");
- main.getHibernateTemplate().save(c1);
关于延迟加载:
http://blog.csdn.net/z69183787/article/details/20049409
http://blog.csdn.net/z69183787/article/details/17136627
http://blog.csdn.net/z69183787/article/details/8197106
http://blog.csdn.net/z69183787/article/details/18615577
一对一基于主键的注解版关系映射
hibernate中一对一的关联有两种方式:一种是采用外键关联,另外一种是采用主键关联。
项目中用到Hibernate(annotation注解方式)构建实体类,其中有一对一主键双向关联。期间遇到一些问题,现在贴出来探讨探讨。 一个帖子内容类(PostText)对应一个帖子信息类(Post),主要目标是在存储帖子或者帖子内容时,关联的对象也被存储。具体代码如下:
- <span style="color: #0000ff;">Post类</span>
- @Entity
- @Table(name = "posts")
- public class Post implements Serializable {
- @Id
- @GeneratedValue(strategy = GenerationType.AUTO) <span style="color: #ff0000;">//主键生成器</span>
- @Column(name="post_id",unique=true)
- private int id;
- @Column(name ="topic_id",nullable=false)
- private int topicId;
- @Column(name ="forum_id",nullable=false)
- private int forumId;
- @OneToOne(cascade=CascadeType.ALL)
- @PrimaryKeyJoinColumn<span style="color: #ff0000;">//这个注解只能写在主(生成ID)的一端</span>
- private PostText postText;
- <span style="color: #008000;">/*相应的get和set方法。。。*/ </span>
- <span style="color: #0000ff;">PostText类</span>
- @Entity
- @Table(name = "jforum_posts_text")
- public class PostText implements Serializable {
- @Id
- @GenericGenerator(name ="pkGenerator",strategy="foreign" ,parameters={@Parameter(name="property",value="post")})
- @GeneratedValue(generator="pkGenerator")
- <span style="color: #ff0000;">//post_text的ID是根据post的ID来赋值的,这里需要设置ID生成器的策略为foreign,参数中指定post_text的ID是使用post对象中的ID</span>
- private int id;
- @Column(name ="post_text",nullable=true)
- private String text;
- @Column(name ="post_subject",nullable=true)
- private String subject;
- @OneToOne(cascade=CascadeType.ALL, mappedBy="postText") <span style="color: #ff0000;">// 一对一</span>
- private Post post;
各种关系映射总结
这个在实际项目中用的比较少,大部分是通过用外键做关联的,这里用用户和手机号举个例子,用户和手机号是一对一的关系,代码如下:
User实体
- package com.own.model;
- import java.io.Serializable;
- public class Users implements Serializable{
- private static final long serialVersionUID = 1381652232198529039L;
- private int id;
- private String username;
- private String password;
- private CellphoneNumber phoneNumber;
- public CellphoneNumber getPhoneNumber() {
- return phoneNumber;
- }
- public void setPhoneNumber(CellphoneNumber phoneNumber) {
- this.phoneNumber = phoneNumber;
- }
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public String getUsername() {
- return username;
- }
- public void setUsername(String username) {
- this.username = username;
- }
- public String getPassword() {
- return password;
- }
- public void setPassword(String password) {
- this.password = password;
- }
- }
手机号实体
- package com.own.model;
- import java.io.Serializable;
- public class CellphoneNumber implements Serializable {
- private static final long serialVersionUID = -1029364968566042141L;
- private Integer cellPhoneId;
- private String number;
- private String attribution;//手机归属地
- private String cellphonoeType;//移动或者联通
- private Users user ;
- public Users getUser() {
- return user;
- }
- public void setUser(Users user) {
- this.user = user;
- }
- public Integer getCellPhoneId() {
- return cellPhoneId;
- }
- public void setCellPhoneId(Integer cellPhoneId) {
- this.cellPhoneId = cellPhoneId;
- }
- public String getNumber() {
- return number;
- }
- public void setNumber(String number) {
- this.number = number;
- }
- public String getAttribution() {
- return attribution;
- }
- public void setAttribution(String attribution) {
- this.attribution = attribution;
- }
- public String getCellphonoeType() {
- return cellphonoeType;
- }
- public void setCellphonoeType(String cellphonoeType) {
- this.cellphonoeType = cellphonoeType;
- }
- @Override
- public boolean equals(Object anotherObject){
- if(anotherObject == null || anotherObject.getClass() != this.getClass()){
- return false;
- }
- if(this == anotherObject){
- return true;
- }
- CellphoneNumber another = (CellphoneNumber) anotherObject;
- if(another.cellPhoneId.equals(this.cellPhoneId)){
- return true ;
- }
- return false;
- }
- public int hashCode(){
- return cellPhoneId.hashCode();
- }
- }
users映射文件
- <?xml version="1.0"?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
- <hibernate-mapping >
- <class name="com.own.model.Users" table="users" dynamic-update="true" dynamic-insert="true" >
- <id name="id" column="id" >
- <generator class="native"></generator>
- </id>
- <property name="username" column="username" ></property>
- <property name="password" column="password" type="string" ></property>
- <!-- 这里是一对一映射 级联为所有 -->
- <one-to-one name="phoneNumber" class="com.own.model.CellphoneNumber" cascade="all" >
- </one-to-one>
- </class>
- </hibernate-mapping>
cellPhone映射文件
- <?xml version="1.0"?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
- <hibernate-mapping >
- <class name="com.own.model.CellphoneNumber" table="cellphone" dynamic-update="true" dynamic-insert="true" >
- <!-- 这里设置外键关联 -->
- <id name="cellPhoneId" column="id" >
- <generator class="foreign">
- <!-- 这里设置用引用user实体的主键 -->
- <param name="property">user</param>
- </generator>
- </id>
- <property name="number" column="cellphoneNumber" ></property>
- <property name="attribution" column="attribution" ></property>
- <property name="cellphonoeType" column="numberType" ></property>
- <!-- 加上外键约束 ,使Cellphone的主键引用user表行的主键 -->
- <one-to-one name="user" constrained="true" class="com.own.model.Users" ></one-to-one>
- </class>
- </hibernate-mapping>
在调用时,要设置关联关系
- Users u = new Users();
- u.setPassword("admin@1973");
- u.setUsername("floatSnow");
- CellphoneNumber cellphone = new CellphoneNumber();
- cellphone.setAttribution("北京");
- cellphone.setCellphonoeType("中国移动");
- cellphone.setNumber("13476534589");
- //设置双向关联关系
- u.setPhoneNumber(cellphone);
- cellphone.setUser(u);
jpa中使用@PrimaryKeyJoinColumn
- package com.own.model;
- import java.io.Serializable;
- import javax.persistence.CascadeType;
- import javax.persistence.Column;
- import javax.persistence.Entity;
- import javax.persistence.GeneratedValue;
- import javax.persistence.Id;
- import javax.persistence.OneToOne;
- import javax.persistence.PrimaryKeyJoinColumn;
- import javax.persistence.Table;
- @Entity
- @org.hibernate.annotations.Entity(dynamicInsert=true,dynamicUpdate=true)
- @Table(name="users")
- public class Users implements Serializable{
- private static final long serialVersionUID = 1381652232198529039L;
- private int id;
- private String username;
- private String password;
- private CellphoneNumber cellphone;
- @OneToOne(cascade={CascadeType.ALL})
- @PrimaryKeyJoinColumn
- public CellphoneNumber getCellphone() {
- return cellphone;
- }
- public void setCellphone(CellphoneNumber cellphone) {
- this.cellphone = cellphone;
- }
- @Id
- @GeneratedValue
- @Column(name="id")
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- @Column(name="username")
- public String getUsername() {
- return username;
- }
- public void setUsername(String username) {
- this.username = username;
- }
- @Column(name="password")
- public String getPassword() {
- return password;
- }
- public void setPassword(String password) {
- this.password = password;
- }
- }
2.一对一外键关联
hibernate xml文件映射,在这里使用manyToOne而不是我们想像的oneToOne,还有在 user表中加一个外键,引用另一个表的主键,这里设置双向关系,在项目中根据情况而定是否设置双向关系
映射文件
- <?xml version="1.0"?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
- <hibernate-mapping >
- <class name="com.own.model.Users" table="users" dynamic-update="true" dynamic-insert="true" >
- <id name="id" column="id" >
- <generator class="native"></generator>
- </id>
- <property name="username" column="username" ></property>
- <property name="password" column="password" type="string" ></property>
- <!-- 加上唯一约束,使这个关系成为真正的一对一 -->
- <many-to-one name="phoneNumber" cascade="all" class="com.own.model.CellphoneNumber" column="cell_id"
- unique="true" >
- </many-to-one>
- </class>
- </hibernate-mapping>
jpa 映射使用oneToone,@joinColumn有两个属性 name 和 referencedColumnName
,name是表示表中外键的列名,referencedColumnName表示外键引用的表的列名。
user实体
- @OneToOne(cascade={CascadeType.ALL})
- @JoinColumn(name="cell_id",referencedColumnName="id")
- public CellphoneNumber getCellphone() {
- return cellphone;
- }
手机实体类
- @OneToOne(mappedBy="cellphone")
- ublic Users getU() {
- return u;
3.一对一可选关联
有的时候我们的外键是可选的,也就是说user表的外键是可以为空的,这个时候我们可以把这中可选的关联映射到一张表,加一张中间表,表示实体的对应关系
Users实体映射文件
- <?xml version="1.0"?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
- <hibernate-mapping >
- <class name="com.own.model.Users" table="users" dynamic-update="true" dynamic-insert="true" >
- <id name="id" column="id" >
- <generator class="native"></generator>
- </id>
- <property name="username" column="username" ></property>
- <property name="password" column="password" type="string" ></property>
- <!-- 加上唯一约束,使这个关系成为真正的一对一 -->
- <!-- optional 告诉hibernate这个关系是可选的 ,当这个属性为空时,可以不插入关联表 -->
- <join table="user_cellphoneNumber" >
- <key column="user_id" unique="true" />
- <many-to-one name="phoneNumber" cascade="save-update" class="com.own.model.CellphoneNumber" column="cell_id"
- unique="true" >
- </many-to-one>
- </join>
- </class>
- </hibernate-mapping>
jpa注解把属性映射到两张表,通过使用@SecondaryTable,使属性映射到一张中间表。
- package com.own.model;
- import java.io.Serializable;
- import javax.persistence.CascadeType;
- import javax.persistence.Column;
- import javax.persistence.Entity;
- import javax.persistence.GeneratedValue;
- import javax.persistence.Id;
- import javax.persistence.JoinColumn;
- import javax.persistence.OneToOne;
- import javax.persistence.PrimaryKeyJoinColumn;
- import javax.persistence.SecondaryTable;
- import javax.persistence.Table;
- import org.hibernate.transaction.JOnASTransactionManagerLookup;
- @Entity
- @org.hibernate.annotations.Entity(dynamicInsert=true,dynamicUpdate=true)
- @Table(name="users")
- @SecondaryTable(name="user_cellphoneNumber",pkJoinColumns={@PrimaryKeyJoinColumn(name="user_id",referencedColumnName="id")})
- public class Users implements Serializable{
- private static final long serialVersionUID = 1381652232198529039L;
- private int id;
- private String username;
- private String password;
- private CellphoneNumber cellphone;
- @OneToOne(cascade={CascadeType.ALL})
- @JoinColumn(table="user_cellphoneNumber",name="cell_id",referencedColumnName="id")
- public CellphoneNumber getCellphone() {
- return cellphone;
- }
- public void setCellphone(CellphoneNumber cellphone) {
- this.cellphone = cellphone;
- }
- @Id
- @GeneratedValue
- @Column(name="id")
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- @Column(name="username")
- public String getUsername() {
- return username;
- }
- public void setUsername(String username) {
- this.username = username;
- }
- @Column(name="password")
- public String getPassword() {
- return password;
- }
- public void setPassword(String password) {
- this.password = password;
- }
- }
4.一对多关联
一对多关联通过oneToMany和ManyToMany映射,这里的多段在java里用一个集合set来表示,这个用商品category和货物Goods来举例子。
one端实体Category 映射xml
- <?xml version="1.0"?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
- <hibernate-mapping >
- <class name="com.own.model.Category" table="category" dynamic-insert="true" dynamic-update="false" >
- <id name="category_id" column="id" >
- <generator class="native"></generator>
- </id>
- <property name="categoryName" column="category_name" type="string" ></property>
- <set name="goodsSet" inverse="true" cascade="save-update" > <!-- 用key column 的名字表示关联表的外键的名称 -->
- <key column="category_id" />
- <one-to-many class="com.own.model.Goods" />
- </set>
- </class>
- </hibernate-mapping>
many端的映射文件
- <?xml version="1.0"?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
- <hibernate-mapping >
- <class name="com.own.model.Goods" table="goods" dynamic-insert="true" dynamic-update="false" >
- <id name="id" column="goods_id" >
- <generator class="native"></generator>
- </id>
- <property name="price" column="goods_price" type="double" ></property>
- <property name="goodsName" column="goods_name" type="string" ></property>
- <property name="goodsDescription" column="goods_description" type="string" ></property>
- <many-to-one name="category" fetch="join" class="com.own.model.Category" column="category_id" >
- </many-to-one>
- </class>
- </hibernate-mapping>
jpa元数据注解
Category实体
- package com.own.model;
- import java.io.Serializable;
- import java.util.HashSet;
- import java.util.Set;
- import javax.persistence.CascadeType;
- import javax.persistence.Column;
- import javax.persistence.Entity;
- import javax.persistence.GeneratedValue;
- import javax.persistence.Id;
- import javax.persistence.OneToMany;
- import javax.persistence.Table;
- @Entity
- @org.hibernate.annotations.Entity(dynamicInsert=true,dynamicUpdate=true)
- @Table(name="category")
- public class Category implements Serializable {
- private static final long serialVersionUID = 1L;
- private Integer category_id;
- private String categoryName;
- private Set<Goods> goodsSet = new HashSet<Goods>();
- @OneToMany(mappedBy="category",cascade={CascadeType.ALL})
- public Set<Goods> getGoodsSet() {
- return goodsSet;
- }
- public void setGoodsSet(Set<Goods> goodsSet) {
- this.goodsSet = goodsSet;
- }
- @Id
- @GeneratedValue
- @Column(name="id")
- public Integer getCategory_id() {
- return category_id;
- }
- public void setCategory_id(Integer categoryId) {
- category_id = categoryId;
- }
- @Column(name="category_name")
- public String getCategoryName() {
- return categoryName;
- }
- public void setCategoryName(String categoryName) {
- this.categoryName = categoryName;
- }
- }
Goods实体
- package com.own.model;
- import java.io.Serializable;
- import javax.persistence.Column;
- import javax.persistence.Entity;
- import javax.persistence.GeneratedValue;
- import javax.persistence.GenerationType;
- import javax.persistence.Id;
- import javax.persistence.JoinColumn;
- import javax.persistence.ManyToOne;
- import javax.persistence.Table;
- @Entity
- @org.hibernate.annotations.Entity(dynamicInsert=true,dynamicUpdate=true)
- @Table(name="goods")
- public class Goods implements Serializable {
- private static final long serialVersionUID = 1L;
- private Integer id;
- private String goodsName;
- private Double price;
- private String goodsDescription;
- private Category category;
- @ManyToOne
- @JoinColumn(name="category_id",referencedColumnName="id")
- public Category getCategory() {
- return category;
- }
- public void setCategory(Category category) {
- this.category = category;
- }
- public Goods(){}
- @Id
- @GeneratedValue(strategy=GenerationType.AUTO)
- @Column(name="goods_id")
- public Integer getId() {
- return id;
- }
- public void setId(Integer id) {
- this.id = id;
- }
- @Column(name="goods_name",length=40,nullable=false)
- public String getGoodsName() {
- return goodsName;
- }
- public void setGoodsName(String goodsName) {
- this.goodsName = goodsName;
- }
- @Column(name="goods_price")
- public Double getPrice() {
- return price;
- }
- public void setPrice(Double price) {
- this.price = price;
- }
- @Column(name="goods_description")
- public String getGoodsDescription() {
- return goodsDescription;
- }
- public void setGoodsDescription(String goodsDescription) {
- this.goodsDescription = goodsDescription;
- }
- @Override
- public boolean equals(Object o) {
- if(o == null || o.getClass() != this.getClass()){
- return false;
- }
- if(o == this){
- return true;
- }
- Goods goods = (Goods) o;
- if(id == null ? goods.id == null : this.id.equals(goods.id)){
- return true;
- }
- return false;
- }
- /*@Override
- public int hashCode() {
- //return this.id.hashCode();
- return
- }*/
- }
5.多对多关联
多对多关联用manyToMany来映射,这里用学生和选的课程,它们是多对多的关联,多对对
关联通常需要一张中间表,这个表就两字段,学生id和课程id(这里中间表就两个字段)
在java中用两set集合来表示
student 映射文件
- <?xml version="1.0"?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
- <hibernate-mapping >
- <class name="com.own.model.Student" table="student" dynamic-update="true" dynamic-insert="true" >
- <id name="studentId" column="id" >
- <generator class="native"></generator>
- </id>
- <property name="studentName" column="student_name" ></property>
- <property name="studentNum" column="student_no" type="string" ></property>
- <set name="cosrseSet" table="student_course" >
- <!-- 引用当前实体主键的外键名称 -->
- <key column="student_id" />
- <many-to-many column="course_id" class="com.own.model.Course" ></many-to-many>
- </set>
- </class>
- </hibernate-mapping>
course映射文件
- <?xml version="1.0"?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
- <hibernate-mapping >
- <class name="com.own.model.Course" table="course" dynamic-update="true" dynamic-insert="true" >
- <id name="courseId" column="id" >
- <generator class="native"></generator>
- </id>
- <property name="courseName" column="course_name" ></property>
- <property name="courseNum" column="course_no" ></property>
- <set name="studentSet" inverse="true" cascade="all" table="student_course" >
- <key column="course_id" />
- <many-to-many column="student_id" class="com.own.model.Student" ></many-to-many>
- </set>
- </class>
- </hibernate-mapping>
jpa元数据
Student实体
- package com.own.model;
- import java.io.Serializable;
- import java.util.HashSet;
- import java.util.Set;
- import javax.persistence.Column;
- import javax.persistence.Entity;
- import javax.persistence.GeneratedValue;
- import javax.persistence.Id;
- import javax.persistence.JoinColumn;
- import javax.persistence.JoinTable;
- import javax.persistence.ManyToMany;
- import javax.persistence.Table;
- @Entity
- @Table(name="student")
- public class Student implements Serializable {
- private static final long serialVersionUID = 1L;
- private Integer studentId;
- private String studentName;
- private String studentNum;
- private Set<Course> cosrseSet = new HashSet<Course>();
- @ManyToMany
- @JoinTable(name="student_course",joinColumns={@JoinColumn(name="student_id")},
- inverseJoinColumns={@JoinColumn(name="course_id")})
- public Set<Course> getCosrseSet() {
- return cosrseSet;
- }
- public void setCosrseSet(Set<Course> cosrseSet) {
- this.cosrseSet = cosrseSet;
- }
- @Id
- @GeneratedValue
- @Column(name="id")
- public Integer getStudentId() {
- return studentId;
- }
- public void setStudentId(Integer studentId) {
- this.studentId = studentId;
- }
- @Column(name="student_name")
- public String getStudentName() {
- return studentName;
- }
- public void setStudentName(String studentName) {
- this.studentName = studentName;
- }
- @Column(name="student_no")
- public String getStudentNum() {
- return studentNum;
- }
- public void setStudentNum(String studentNum) {
- this.studentNum = studentNum;
- }
- }
Course实体
- package com.own.model;
- import java.io.Serializable;
- import java.util.HashSet;
- import java.util.Set;
- import javax.persistence.Column;
- import javax.persistence.Entity;
- import javax.persistence.GeneratedValue;
- import javax.persistence.Id;
- import javax.persistence.ManyToMany;
- import javax.persistence.Table;
- @Entity
- @Table(name="course")
- public class Course implements Serializable {
- private static final long serialVersionUID = 1L;
- private Integer courseId;
- private String courseNum;
- private String courseName;
- private Set<Student> studentSet = new HashSet<Student>();
- @ManyToMany(mappedBy="cosrseSet")
- public Set<Student> getStudentSet() {
- return studentSet;
- }
- public void setStudentSet(Set<Student> studentSet) {
- this.studentSet = studentSet;
- }
- @Id
- @GeneratedValue
- @Column(name="id")
- public Integer getCourseId() {
- return courseId;
- }
- public void setCourseId(Integer courseId) {
- this.courseId = courseId;
- }
- @Column(name="course_no")
- public String getCourseNum() {
- return courseNum;
- }
- public void setCourseNum(String courseNum) {
- this.courseNum = courseNum;
- }
- @Column(name="course_name")
- public String getCourseName() {
- return courseName;
- }
- public void setCourseName(String courseName) {
- this.courseName = courseName;
- }
- /* @Override
- public boolean equals(Object o) {
- if(o == null || o.getClass() != Course.class){
- return false;
- }
- if(o == this){
- return true;
- }
- Course another = (Course)o;
- if(courseId == null ? another.courseId == null : courseId.equals(another.courseId)){
- return true;
- }
- return false;
- }
- @Override
- public int hashCode() {
- return super.hashCode();
- // return 1;
- }*/
- }
在多对对关联的情况下,用的是set集合,实体要实现hashcode和equals,不然在更新关联表的时候会更新不了,比如学生不在选择这门课程,从set集合中remove掉这个课程,然后更新这个学生实体,代码如下,在不实现hashcode和equals更新不会成功,只有实现了才可以,hibernate返回了自己写的集合,PersistenceSet而不是HashSet,这也是为什么我们在实体中写set接口,不能写HashSet ... = new HashSet,要用 Set ... = new HashSet 。
- tc = session.beginTransaction();
- Student s1 = (Student) session.get(Student.class,9) ;
- Course c = new Course();
- s1.getCosrseSet().remove(c);
- session.update(s1);//更新学生的选课
- tc.commit();
最后讲解一下cascade和inverse这两个属性,刚用hibernate的时候也比较不理解,首先这两个属性没有任何关系,cascade表示级联,就是被关联的一段,比如cascade='save-update',级联保存和更新,在设置了cascade的端,保存这个对象,会一并保存关联的一端,省去了我们写保存关联端的代码,inverse表示有谁来维护关联,在一段设置inverse=true,则有关联对来维护关联关系,比如上面的例子,在course端设置了inverse=true,则有student来维护中间表,只有当插入student的时候,才向中间表插入数据,如果都设置inverse=true则会插入重复数据,如果不设置,则会出错,在jpa元数据注解中 用mappedBy来表示有那方来维护关联关系