两个类用户信息和用户Tag类型 多对多的关系
1.用户信息类
package com.yunmiao.bean.player;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import org.hibernate.annotations.Cascade;
import org.springframework.format.annotation.DateTimeFormat;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.yunmiao.bean.base.BaseModel;
/**
* @ClassName: PlayerBindInfo
* @Description: 玩家绑定的个人信息
* @author Jay He
* @date 2015年8月31日 上午11:13:35
*
*/
@Entity
@Table(name="player_bind_info", catalog="vgame")
public class PlayerBindInfo extends BaseModel{
private static final long serialVersionUID = 9138118201233047164L;
// 跟服务器关联的用户名 规则: agentId-serverId-用户id
private String uname;
private Set<PlayerTagType> tags = new HashSet<>();
// 用户真实姓名
private String name;
//性别
private short sex;
//年龄
private Integer age;
// 生日
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8") //取日期时使用
@DateTimeFormat(pattern = "yyyy-MM-dd")//存日期时使用
private Date birthday;
// 电话
private String phone;
private String email;
private String qq;
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
@ManyToMany(cascade = { CascadeType.PERSIST }, targetEntity = PlayerTagType.class, fetch = FetchType.EAGER)
@JoinTable(name = "palyer_info_tag", joinColumns = { @JoinColumn(name = "player_info_id", updatable = true) }, inverseJoinColumns = { @JoinColumn(name = "tag_id", updatable = true) })
@Cascade(value = { org.hibernate.annotations.CascadeType.SAVE_UPDATE })
public Set<PlayerTagType> getTags() {
return tags;
}
public void setTags(Set<PlayerTagType> tags) {
this.tags = tags;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public short getSex() {
return sex;
}
public void setSex(short sex) {
this.sex = sex;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getQq() {
return qq;
}
public void setQq(String qq) {
this.qq = qq;
}
}
package com.yunmiao.bean.player;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import org.hibernate.annotations.Cascade;
import com.yunmiao.bean.base.BaseModel;
/**
* @ClassName: PlayerTagType
* @Description: 玩家绑定个人信息的Tag类型,即组别
* @author Jay He
* @date 2015年8月31日 上午11:14:47
*
*/
@Entity
@Table(name = "player_bind_tag", catalog = "vgame")
public class PlayerTagType extends BaseModel {
private static final long serialVersionUID = -1798421553058039290L;
// Tag名称
private String name;
// Tag唯一的Code标识
private String code;
// 描述
private String description;
// Tag下的所有玩家
private List<PlayerBindInfo> players;
@Column(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column(name = "code")
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
@Column(name = "description")
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
/*
* 这里的mappedBy标识在另一方的多对多中,本类被引用的Set的名称,这里是tags
* cascade={CascadeType.REMOVE,CascadeType.PERSIST} -- 表示级联删除和级联保存
*/
@ManyToMany(cascade={CascadeType.MERGE,CascadeType.PERSIST},
mappedBy = "tags", targetEntity = PlayerBindInfo.class)
public List<PlayerBindInfo> getPlayers() {
return players;
}
public void setPlayers(List<PlayerBindInfo> players) {
this.players = players;
}
}
1.信息表
@ManyToMany(cascade = { CascadeType.PERSIST }, targetEntity = PlayerTagType.class, fetch = FetchType.EAGER)
@JoinTable(name = "palyer_info_tag", joinColumns = { @JoinColumn(name = "player_info_id", updatable = true) }, inverseJoinColumns = { @JoinColumn(name = "tag_id", updatable = true) })
@Cascade(value = { org.hibernate.annotations.CascadeType.SAVE_UPDATE })
public Set<PlayerTagType> getTags() {
return tags;
}
cascade:配置级联操作 --- 根据实际情况进行配置
CascadeType. PERSIST 级联持久化 ( 保存 ) 操作
CascadeType. MERGE 级联更新 ( 合并 ) 操作
CascadeType. REFRESH 级联刷新操作,只会查询获取操作
CascadeType. REMOVE 级联删除操作
CascadeType. ALL 级联以上全部操作 ---- 默认
JoinTable : 配置中间表
name : 中间表表名
joinClolumns : 当前类在中间表中的外键字段
inverseJoinColumns : 另一个被关联表在中间表中的外键字段
2.Tag表
@ManyToMany(cascade={CascadeType.MERGE,CascadeType.PERSIST},
mappedBy = "tags", targetEntity = PlayerBindInfo.class)
public List<PlayerBindInfo> getPlayers() {
return players;
}
cascade : 级联操作 --- 同上面一样
mappedBy : 本类在另一个类中的引用名称,在Info类中是 private Set<PlayerTagType> tags = new HashSet<>(); 所以这里陪只为 tags
targetEntity : mappedBy 的类型 --- 即tags所在的那个类
我这里的需求是 ---- 级联删除与不级联删除
1.级联删除 即: 删除Tag表的记录后,用户信息表与该Tag关联的也全部删掉
修改Tag表manytomany为 cascade={CascadeType.ALL}或者添加CascadeType.REMOVE ---- 表示级联删除
@ManyToMany(cascade={CascadeType.MERGE,CascadeType.PERSIST,<span style="font-family: Arial, Helvetica, sans-serif;">CascadeType.REMOVE</span>},
mappedBy = "tags", targetEntity = PlayerBindInfo.class)
public List<PlayerBindInfo> getPlayers() {
return players;
}
2.非级联删除 即:删除Tag表的记录后,只删除中间表中与该Tag有关的记录,而不删除用户信息表中记录 --- 删除Tag,不影响Info表
1. 修改Tag表中的manytomany 去掉 CascadeType.REMOVE,注意不能在使用CascadeType.ALL(这个事默认配置,表示级联删除)
2. 修改表结构,去数据库中设置外键中间表的关联关系为delete cascade,如下图,将中间表的tag_id的删除时由RESTRICT改为CASCADE即可
3.测试代码
import java.util.HashSet;
import java.util.Set;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.yunmiao.bean.player.PlayerBindInfo;
import com.yunmiao.bean.player.PlayerTagType;
import com.yunmiao.service.player.PlayerBindInfoService;
import com.yunmiao.service.player.PlayerTagTypeService;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:/spring/*.xml")
public class PlayerTest {
@Autowired
private PlayerBindInfoService playerService;
@Autowired
private PlayerTagTypeService tagService;
@Test
public void test1(){
Set<PlayerTagType> set = new HashSet<>();
PlayerTagType tag = new PlayerTagType();
tag.setName("VIP");
tag.setCode("vip");
tag.setDescription("VIP组");
//tagService.save(tag);
set.add(tag);
PlayerBindInfo info = new PlayerBindInfo();
info.setAge(10);
info.setEmail("3rel23j4@qq.com");
info.setQq("32432434");
info.setPhone("23434322222222");
info.setTags(set);
playerService.save(info);
}
@Test
public void test2(){
tagService.delete(PlayerTagType.class, "402881f34f8293fe014f82940bd90001");
}
}