JPA(六)多对多
程序员文章站
2022-03-02 15:28:30
...
1.多对多实体类配置
@Entity
@Table(name = "role")
public class Role {
@Id
@Column(name = "role_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long roleId;
@Column(name = "role_name")
private String roleName;
@ManyToMany(cascade=CascadeType.ALL)
@JoinTable(name = "user_role", joinColumns = {@JoinColumn(name = "rid",referencedColumnName="role_id")},
inverseJoinColumns = {@JoinColumn(name = "uid",referencedColumnName="user_id")})
private Set<Users> userList = new HashSet<>();
}
@Entity
@Table(name = "users")
public class Users {
@Id
@Column(name = "user_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long userId;
@Column(name = "user_name")
private String userName;
@Column(name = "user_address")
private String address;
@Column(name = "user_gender")
private String gender;
@ManyToMany(cascade=CascadeType.ALL,mappedBy="userList")
private Set<Role> roles = new HashSet<>(0);
}
2、注解说明
- @ManyToMany
作用:
用于映射多对多关系
属性:
cascade:配置级联操作。
fetch:配置是否采用延迟加载。
targetEntity:配置目标的实体类。映射多对多的时候不用写。
-
@JoinTable
作用:
针对中间表的配置
属性:
nam:配置中间表的名称
joinColumns:中间表的外键字段关联当前实体类所对应表的主键字段
inverseJoinColumn:中间表的外键字段关联对方表的主键字段
- @JoinColumn
作用:
用于定义主键字段和外键字段的对应关系。
属性:
name:指定外键字段的名称
referencedColumnName:指定引用主表的主键字段名称
unique:是否唯一。默认值不唯一
nullable:是否允许为空。默认值允许。
insertable:是否允许插入。默认值允许。
updatable:是否允许更新。默认值允许。
columnDefinition:列的定义信息。
3测试
3.1、保存
/**
*
* 1、保存一个实体
*/
@Test
public void testAdd() {
// 定义对象
Role role1 = new Role();
Role role2 = new Role();
Users users1 = new Users();
Users users2 = new Users();
role1.setRoleName("角色1");
role1.getUserList().add(users1);
role1.getUserList().add(users2);
role2.setRoleName("角色2");
role2.getUserList().add(users2);
users1.setAddress("北京");
users1.setGender("男");
users1.setUserName("张三");
users1.getRoles().add(role1);
users2.setAddress("上海");
users2.setGender("女");
users2.setUserName("赵四");
users2.getRoles().add(role1);
users2.getRoles().add(role2);
EntityManager em = null;
EntityTransaction tx = null;
try {
// 获取实体管理对象
em = JpaUtil.getEntityManager();
// 获取事务对象
tx = em.getTransaction();
// 开启事务
tx.begin();
// 执行操作
em.persist(role1);
// 提交事务
tx.commit();
} catch (Exception e) {
// 回滚事务
tx.rollback();
e.printStackTrace();
} finally {
// 释放资源
em.close();
}
}
在多对多(保存)中,如果双向都设置关系,意味着双方都维护中间表,都会往中间表插入数据,中间表的 2
个字段又作为联合主键,所以报错,主键重复,解决保存失败的问题:只需要在任意一方放弃对中间表的维护权即
可,推荐在被动的一方放弃,配置如下:
@ManyToMany(mappedBy="roles")
private Set<SysUser> users = new HashSet<SysUser>(0);
3.2删除
/**
* 删除操作
* 删除从表数据:可以随时任意删除。
* 删除主表数据:
* 有从表数据引用
* 1、不能删除
* 2、如果还想删除,使用级联删除
* 没有从表数据引用:随便删
*
* 在实际开发中,级联删除请慎用!(在一对多的情况下)
*/
@Test
public void testRemove() {
// 定义对象
EntityManager em = null;
EntityTransaction tx = null;
try {
// 获取实体管理对象
em = JpaUtil.getEntityManager();
// 获取事务对象
tx = em.getTransaction();
// 开启事务
tx.begin();
// 执行操作
Users u = em.find(Users.class, 2L);
em.remove(u);
// 提交事务
tx.commit();
} catch (Exception e) {
// 回滚事务
tx.rollback();
e.printStackTrace();
} finally {
// 释放资源
em.close();
}
}
级联删除的配置:
@OneToMany(targetEntity=LinkMan.class,mappedBy="customer",cascade=CascadeType.AL
L) //用 CascadeType.REMOVE 也可以
private Set<LinkMan> linkmans = new HashSet<LinkMan>(0);
上一篇: Java NIO服务器:远程主机强迫关闭了一个现有的连接
下一篇: JAVA NIO