Hibernate第四天
1.JPA相关概念
1.1.JPA概述
1.2.JPA优势
1.3.学习JPA要明确的
a、JPA是一套ORM规范,hibernate实现了JPA规范
b、hibernate中有自己的独立ORM操作数据库方式,也有JPA规范实现的操作数据库方式。
c、在数据库增删改查操作中,我们hibernate和JPA的操作都要会。
2.JPA入门
2.1.第一步:创建工程,引入jar包
注意:除了要引入hibernate5必须的jar包以外,还要引入红框中的这个jar包。
2.2.第二步:创建实体类
在实体类上加上JPA注解,取代传统的hbm.xml文件的功能。需要使用到的注解有:
1、@Entity:如果一个类加上此注解,表示该类是一个实体类。
2、@Table:指定该类所映射的表,name属性表示该类所映射的表名。如果类名与表名一致,此注解可以省略。
3、@Id:表示与主键列对应的属性。
4、@GeneratedValue:表示主键如何生成。strategy属性表示主键的生成策略。GenerationType.IDENTITY表示自动增长。
/**
-
客户实体类
-
@author kevin
*/
@Entity
@Table(name=“cst_customer”)
public class Customer {@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private long cust_id;
private String cust_name;
private String cust_source;
private String cust_industry;
private String cust_level;
private String cust_address;
private String cust_phone;
private String cust_mobile;
public long getCust_id() {
return cust_id;
}
public void setCust_id(long cust_id) {
this.cust_id = cust_id;
}
public String getCust_name() {
return cust_name;
}
public void setCust_name(String cust_name) {
this.cust_name = cust_name;
}
public String getCust_source() {
return cust_source;
}
public void setCust_source(String cust_source) {
this.cust_source = cust_source;
}
public String getCust_industry() {
return cust_industry;
}
public void setCust_industry(String cust_industry) {
this.cust_industry = cust_industry;
}
public String getCust_level() {
return cust_level;
}
public void setCust_level(String cust_level) {
this.cust_level = cust_level;
}
public String getCust_address() {
return cust_address;
}
public void setCust_address(String cust_address) {
this.cust_address = cust_address;
}
public String getCust_phone() {
return cust_phone;
}
public void setCust_phone(String cust_phone) {
this.cust_phone = cust_phone;
}
public String getCust_mobile() {
return cust_mobile;
}
public void setCust_mobile(String cust_mobile) {
this.cust_mobile = cust_mobile;
}
@Override
public String toString() {
return “Customer [cust_id=” + cust_id + “, cust_name=” + cust_name + “, cust_source=” + cust_source
+ “, cust_industry=” + cust_industry + “, cust_level=” + cust_level + “, cust_address=” + cust_address
+ “, cust_phone=” + cust_phone + “, cust_mobile=” + cust_mobile + “]”;
}
}
2.3.第三步:创建配置文件
1、在src下新建META-INF文件夹,新建persistence.xml文件。
2、引入schema约束,可以从hibernate-entitymanager-5.0.7.Final.jar/org/hibernate/jpa/persistence_2_0.xsd中拷贝
3、配置提示
内容如下:
<?xml version="1.0" encoding="UTF-8"?><persistence-unit name="myPersistUnit">
<!-- 指定JPA规范的实现:Hibernate的实现 (可省略)-->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<!-- 指定要被扫描到的实体类 (可省略)-->
<class>cn.itcast.domain.Customer</class>
<properties>
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/hibernate"/>
<property name="hibernate.connection.username" value="root"/>
<property name="hibernate.connection.password" value="123456"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
2.4.第四步:编写工具类,用于获取JPA操作数据库的对象
/**
-
用于获取JPA操作数据库对象的工具类
-
@author kevin
*/
public class JPAUtils {//JPA的实体管理器工厂:相当于Hibernte的SessionFactory
private static final EntityManagerFactory em;
//使用静态代码块赋值
static{
//创建JPA的实体管理器工厂:该方法参数必须和persistence.xml中persistence-unit标签的name属性一致
em = Persistence.createEntityManagerFactory(“myPersistUnit”);
}/**
- 获取实例管理器的工具方法
- @return
/
public static EntityManager getEntityManager(){
return em.createEntityManager();
}
}
2.5.第五步:编写测试类
/* - 测试JPA注解里的保存
/
@Test
public void test1(){
Customer customer = new Customer();
customer.setCust_name(“张三123”);
//获取JPA中实体管理器
EntityManager em = JPAUtils.getEntityManager();
//获取事务
EntityTransaction tx = em.getTransaction();
//开启事务
tx.begin();
//保存对象
em.persist(customer);
//提交事务
tx.commit();
//释放资源
em.close();
}
3.常用注解及主键生成策略
3.1.常用注解说明
@Entity
作用:指定当前类是实体类。写上此注解用于在创建SessionFactory/EntityManager时,加载映射配置。
@Table
作用:指定实体类和表之间的对应关系。
属性:
name:指定数据库表的名称
@Id
作用:指定当前字段是主键。
@GeneratedValue
作用:指定主键的生成方式。JPA的主键生成方式详解见2.4小节的说明。
属性:
strategy :指定主键生成策略。JPA支持四种生成策略,具体介绍看2.4小节。
@Column
作用:指定实体类属性和数据库表之间的对应关系
属性:
name:指定数据库表的列名称。
unique:是否唯一
nullable:是否可以为空
inserttable:是否可以插入
updateable:是否可以更新
columnDefinition: 定义建表时创建此列的DDL
secondaryTable: 从表名。如果此列不建在主表上(默认建在主表),该属性定义该列所在从表的名字。
3.2.主键生成策略
通过annotation(注解)来映射hibernate实体的,基于annotation的hibernate主键标识为@Id,
其生成规则由@GeneratedValue设定的.这里的@id和@GeneratedValue都是JPA的标准用法。
JPA提供的四种标准用法为TABLE,SEQUENCE,IDENTITY,AUTO。具体说明如下:
3.2.1.IDENTITY:主键由数据库自动生成(主要是自动增长型)
用法:
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long custId;
3.2.2.SEQUENCE:根据底层数据库的序列来生成主键,条件是数据库支持序列。
用法:
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,generator=“payablemoney_seq”)
@SequenceGenerator(name=“payablemoney_seq”, sequenceName=“seq_payment”)
说明:
@SequenceGenerator源码中的定义
@Target({TYPE, METHOD, FIELD})
@Retention(RUNTIME)
public @interface SequenceGenerator {
String name();
String sequenceName() default “”;
int initialValue() default 0;
int allocationSize() default 50;
}
name:表示该表主键生成策略的名称,它被引用在@GeneratedValue中设置的“generator”值中。
sequenceName:属性表示生成策略用到的数据库序列名称。
initialValue:表示主键初识值,默认为0。
allocationSize:表示每次主键值增加的大小,例如设置1,则表示每次插入新记录后自动加1,默认为50。
3.2.3.AUTO:根据底层数据库自动选择一种策略
如果底层数据库是mysql,JPA是采用一个特定的表来保存主键。
用法:
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
3.2.4.TABLE:使用一个特定的数据库表格来保存主键(了解)
用法:
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
4.JPA注解的CRUD
4.1.保存
@Test
public void test1(){
Customer customer = new Customer();
customer.setCust_name(“张三123”);
//获取JPA中实体管理器
EntityManager em = JPAUtils.getEntityManager();
//获取事务
EntityTransaction tx = em.getTransaction();
//开启事务
tx.begin();
//保存对象
em.persist(customer);
//提交事务
tx.commit();
//释放资源
em.close();
}
4.2.查询一个
/* - 查询一个
*/
@Test
public void test2(){
//获取JPA中实体管理器
EntityManager em = JPAUtils.getEntityManager();
//获取事务
EntityTransaction tx = em.getTransaction();
//开启事务
tx.begin();
Customer customer = em.find(Customer.class, 1L);
System.out.println(customer);
//提交事务
tx.commit();
//释放资源
em.close();
}
JPA也是有缓存的:
/**
* 查询一个:缓存问题
*/
@Test
public void test2Cache(){
//获取JPA中实体管理器
EntityManager em = JPAUtils.getEntityManager();
//获取事务
EntityTransaction tx = em.getTransaction();
//开启事务
tx.begin();
Customer customer1 = em.find(Customer.class, 1L);
Customer customer2 = em.find(Customer.class, 1L);
System.out.println(customer1==customer2);
//提交事务
tx.commit();
//释放资源
em.close();
}
JPA中也是有延迟加载的:
/**
* 查询一个:延迟加载的问题
/
@Test
public void test2Lazy(){
//获取JPA中实体管理器
EntityManager em = JPAUtils.getEntityManager();
//获取事务
EntityTransaction tx = em.getTransaction();
//开启事务
tx.begin();
Customer customer = em.getReference(Customer.class, 1L);//不发sql语句
System.out.println(customer);//真正要用的时候,才发送select语句
//提交事务
tx.commit();
//释放资源
em.close();
}
4.3.查询所有
/*
* 查询所有:利用JPQL来查询
- JPQL是Java Persistence Query Language,中文含义是Java持久化查询语言
sql中可以给表起别名,例如:select * from cst_customer c
JPQL语法规定:要给类加别名,例如select c from Customer c,表示查询表里有数的数据 - /
@Test
public void test3(){
//获取JPA中实体管理器
EntityManager em = JPAUtils.getEntityManager();
//获取事务
EntityTransaction tx = em.getTransaction();
//开启事务
tx.begin();
Query query = em.createQuery(“select c from Customer c where c.cust_name like ?”);
query.setParameter(1, “%张%”);
List list = query.getResultList();
for(Customer c:list){
System.out.println©;
}
//提交事务
tx.commit();
//释放资源
em.close();
}
细节:JPA中的Query设置参数的位置是从1开始的。
4.4.更新
/*-
修改
*/
@Test
public void update(){
//获取JPA中实体管理器
EntityManager em = JPAUtils.getEntityManager();
//获取事务
EntityTransaction tx = em.getTransaction();
//开启事务
tx.begin();Customer customer = em.find(Customer.class, 1L);
customer.setCust_name(“李四”);
//提交事务
tx.commit();//使用JPA中快照机制实现更新
//释放资源
em.close();
}
-
4.5.删除
/**
* 删除
*/
@Test
public void delete(){
//获取JPA中实体管理器
EntityManager em = JPAUtils.getEntityManager();
//获取事务
EntityTransaction tx = em.getTransaction();
//开启事务
tx.begin();
Customer customer = em.find(Customer.class, 2L);
em.remove(customer);
//提交事务
tx.commit();//使用JPA中快照机制实现更新
//释放资源
em.close();
}
5.JPA多表映射
5.1.一对多关系映射
5.1.1.常用注解
5.1.1.1.@OneToMany
作用:
建立一对多的关系映射
属性:
targetEntityClass:指定多的多方的类的字节码
mappedBy:指定从表实体类中引用主表对象的名称。让主表(一方)放弃外键维护。
cascade:指定要使用的级联操作
fetch:指定是否采用延迟加载
orphanRemoval:是否使用孤儿删除
5.1.1.2.@ManyToOne
作用:
建立多对一的关系
属性:
targetEntityClass:指定一的一方实体类字节码
cascade:指定要使用的级联操作
fetch:指定是否采用延迟加载
optional:关联是否可选。如果设置为false,则必须始终存在非空关系。
5.1.1.3.@JoinColumn
作用:
用于定义主键字段和外键字段的对应关系。
属性:
name:指定外键字段的名称
referencedColumnName:指定引用主表的主键字段名称
unique:是否唯一。默认值不唯一
nullable:是否允许为空。默认值允许。
insertable:是否允许插入。默认值允许。
updatable:是否允许更新。默认值允许。
columnDefinition:列的定义信息。
5.1.2.配置代码
5.1.2.1.客户配置
/**
-
客户实体类
-
@author kevin
*/
@Entity
@Table(name=“cst_customer”)
public class Customer {@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private long cust_id;
private String cust_name;
private String cust_source;
private String cust_industry;
private String cust_level;
private String cust_address;
private String cust_phone;
private String cust_mobile;
//mappedBy属性:表示由多方(联系人)来维护主键,值就是多方(联系人)中一方的属性名
@OneToMany(mappedBy=“customer”)
private Set linkMans = new HashSet();
public long getCust_id() {
return cust_id;
}
public void setCust_id(long cust_id) {
this.cust_id = cust_id;
}
public String getCust_name() {
return cust_name;
}
public void setCust_name(String cust_name) {
this.cust_name = cust_name;
}
public String getCust_source() {
return cust_source;
}
public void setCust_source(String cust_source) {
this.cust_source = cust_source;
}
public String getCust_industry() {
return cust_industry;
}
public void setCust_industry(String cust_industry) {
this.cust_industry = cust_industry;
}
public String getCust_level() {
return cust_level;
}
public void setCust_level(String cust_level) {
this.cust_level = cust_level;
}
public String getCust_address() {
return cust_address;
}
public void setCust_address(String cust_address) {
this.cust_address = cust_address;
}
public String getCust_phone() {
return cust_phone;
}
public void setCust_phone(String cust_phone) {
this.cust_phone = cust_phone;
}
public String getCust_mobile() {
return cust_mobile;
}
public void setCust_mobile(String cust_mobile) {
this.cust_mobile = cust_mobile;
}public Set getLinkMans() {
return linkMans;
}
public void setLinkMans(Set linkMans) {
this.linkMans = linkMans;
}
@Override
public String toString() {
return “Customer [cust_id=” + cust_id + “, cust_name=” + cust_name + “, cust_source=” + cust_source
+ “, cust_industry=” + cust_industry + “, cust_level=” + cust_level + “, cust_address=” + cust_address
+ “, cust_phone=” + cust_phone + “, cust_mobile=” + cust_mobile + “]”;
}
}
5.1.2.2.联系人配置
/** -
联系人实体类
-
@author kevin
*/
@Entity
@Table(name=“cst_linkman”)
public class LinkMan implements Serializable{private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long lkm_id;
private String lkm_name;
private String lkm_gender;
private String lkm_phone;
private String lkm_mobile;
private String lkm_email;
private String lkm_position;
private String lkm_memo;//多对一关系映射:多个联系人对应一个客户
@ManyToOne
@JoinColumn(name=“lkm_customer_id”)
private Customer customer;
public Long getLkm_id() {
return lkm_id;
}
public void setLkm_id(Long lkm_id) {
this.lkm_id = lkm_id;
}
public String getLkm_name() {
return lkm_name;
}
public void setLkm_name(String lkm_name) {
this.lkm_name = lkm_name;
}
public String getLkm_gender() {
return lkm_gender;
}
public void setLkm_gender(String lkm_gender) {
this.lkm_gender = lkm_gender;
}
public String getLkm_phone() {
return lkm_phone;
}
public void setLkm_phone(String lkm_phone) {
this.lkm_phone = lkm_phone;
}
public String getLkm_mobile() {
return lkm_mobile;
}
public void setLkm_mobile(String lkm_mobile) {
this.lkm_mobile = lkm_mobile;
}
public String getLkm_email() {
return lkm_email;
}
public void setLkm_email(String lkm_email) {
this.lkm_email = lkm_email;
}
public String getLkm_position() {
return lkm_position;
}
public void setLkm_position(String lkm_position) {
this.lkm_position = lkm_position;
}
public String getLkm_memo() {
return lkm_memo;
}
public void setLkm_memo(String lkm_memo) {
this.lkm_memo = lkm_memo;
}public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}@Override
public String toString() {
return “LinkMan [lkm_id=” + lkm_id + “, lkm_name=” + lkm_name + “, lkm_gender=” + lkm_gender + “, lkm_phone=”
+ lkm_phone + “, lkm_mobile=” + lkm_mobile + “, lkm_email=” + lkm_email + “, lkm_position=”
+ lkm_position + “, lkm_memo=” + lkm_memo + “]”;
}
}
5.2.多对多关系映射
5.2.1.常用注解
5.2.1.1.@ManyToMany
作用:
用于映射多对多关系
属性:
cascade:配置级联操作。
fetch:配置是否采用延迟加载。
targetEntity:配置目标的实体类。映射多对多的时候不用写。
5.2.1.2.@JoinTable
作用:
针对中间表的配置
属性:
nam:配置中间表的名称
joinColumns:中间表的外键字段关联当前实体类所对应表的主键字段
inverseJoinColumn:中间表的外键字段关联对方表的主键字段
5.2.1.3.@JoinColumn
作用:
用于定义主键字段和外键字段的对应关系。
属性:
name:指定外键字段的名称
referencedColumnName:指定引用主表的主键字段名称
unique:是否唯一。默认值不唯一
nullable:是否允许为空。默认值允许。
insertable:是否允许插入。默认值允许。
updatable:是否允许更新。默认值允许。
columnDefinition:列的定义信息。
5.2.2.配置代码
5.2.2.1.用户配置
/**
-
用户实体类
-
@author kevin
*/
@Entity
@Table(name=“sys_user”)
public class SysUser implements Serializable{private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long user_id;
private String user_code;
private String user_name;
private String user_password;
private String user_state;//多对多关系映射
@ManyToMany
@JoinTable(name=“user_role”,joinColumns=@JoinColumn(name=“user_id”),inverseJoinColumns=@JoinColumn(name=“role_id”))
private Set roles = new HashSet();public Long getUser_id() {
return user_id;
}
public void setUser_id(Long user_id) {
this.user_id = user_id;
}
public String getUser_code() {
return user_code;
}
public void setUser_code(String user_code) {
this.user_code = user_code;
}
public String getUser_name() {
return user_name;
}
public void setUser_name(String user_name) {
this.user_name = user_name;
}
public String getUser_password() {
return user_password;
}
public void setUser_password(String user_password) {
this.user_password = user_password;
}
public String getUser_state() {
return user_state;
}
public void setUser_state(String user_state) {
this.user_state = user_state;
}
public Set getRoles() {
return roles;
}
public void setRoles(Set roles) {
this.roles = roles;
}
@Override
public String toString() {
return “SysUser [user_id=” + user_id + “, user_code=” + user_code + “, user_name=” + user_name
+ “, user_password=” + user_password + “, user_state=” + user_state + “, roles=” + roles + “]”;
}
}
5.2.2.2.角色配置
/**
-
角色实体类
-
@author kevin
*/
@Entity
@Table(name=“sys_role”)
public class SysRole implements Serializable {private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long role_id;
private String role_name;
private String role_memo;//一个角色对应多个用户
@ManyToMany(mappedBy=“roles”)
private Set users = new HashSet();
public Long getRole_id() {
return role_id;
}
public void setRole_id(Long role_id) {
this.role_id = role_id;
}
public String getRole_name() {
return role_name;
}
public void setRole_name(String role_name) {
this.role_name = role_name;
}
public String getRole_memo() {
return role_memo;
}
public void setRole_memo(String role_memo) {
this.role_memo = role_memo;
}
public Set getUsers() {
return users;
}
public void setUsers(Set users) {
this.users = users;
}
@Override
public String toString() {
return “SysRole [role_id=” + role_id + “, role_name=” + role_name + “, role_memo=” + role_memo + “, users=”
+ users + “]”;
}
}
6.JPA多表操作
6.1.一对多关系的增删改操作
6.1.1.保存操作
/**
* 一对多保存
* 建立双向关系
*/
@Test
public void test1(){
Customer customer = new Customer();
customer.setCust_name(“客户1”);
LinkMan linkMan = new LinkMan();
linkMan.setLkm_name(“联系人1”);
//建立客户和联系人的双向关系,不会有多余的update语句,因为我们在一方(客户)加了mappedBy,放弃了外键维护权
customer.getLinkMans().add(linkMan);
linkMan.setCustomer(customer);
EntityManager em = JPAUtils.getEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
em.persist(customer);
em.persist(linkMan);
tx.commit();
em.close();
}
如果想级联保存,在Customer实体类的@OneToMany注解中加上级联保存属性:
//一个客户有多个联系人
//mappedBy属性:表示由多方(联系人)来维护主键,值就是多方(联系人)中一方的属性名
@OneToMany(mappedBy=“customer”,cascade=CascadeType.PERSIST)
/**
* 一对多级联保存:保存客户级联保存联系人
* 在Customer实体类的OneToMany注解中加cascade=CascadeType.PERSIST
*
*/
@Test
public void test2(){
Customer customer = new Customer();
customer.setCust_name(“客户1”);
LinkMan linkMan = new LinkMan();
linkMan.setLkm_name(“联系人1”);
//建立客户和联系人的双向关系,不会有多余的update语句,因为我们在一方(客户)加了mappedBy,放弃了外键维护权
customer.getLinkMans().add(linkMan);
linkMan.setCustomer(customer);
EntityManager em = JPAUtils.getEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
em.persist(customer);
tx.commit();
em.close();
}
6.1.2.删除操作
这里直接演示删除客户级联删除联系人。
如果想级联删除,可以在客户这边配置级联删除
提示:如果想配置多个级联操作,可以这样来配置:cascade={CascadeType.PERSIST,CascadeType.REMOVE}
//一个客户有多个联系人
//mappedBy属性:表示由多方(联系人)来维护主键,值就是多方(联系人)中一方的属性名
@OneToMany(mappedBy=“customer”,cascade={CascadeType.PERSIST,CascadeType.REMOVE})
private Set linkMans = new HashSet();
/**
* 一对多级联删除:删除客户,级联删除联系人
*
*/
@Test
public void test3(){
EntityManager em = JPAUtils.getEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
Customer custmer = em.find(Customer.class, 1L);
em.remove(custmer);
tx.commit();
em.close();
}
6.1.3.修改操作
/**
* 一对多的更新
* 需求:让2号联系人属于2号客户
*/
@Test
public void test6(){
EntityManager em = JPAUtils.getEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
//先查询id为2的联系人
LinkMan linkMan = em.find(LinkMan.class, 2L);
//再查询id为2的客户
Customer customer = em.find(Customer.class, 2L);
//重新建立关系
linkMan.setCustomer(customer);
tx.commit();
em.close();
}
6.2.多对多关系的增删改操作
6.2.1.保存操作
@Test
public void test1(){
SysUser user1 = new SysUser();
user1.setUser_name(“张三”);
SysUser user2 = new SysUser();
user2.setUser_name("李四");
SysRole role1 = new SysRole();
role1.setRole_name("角色1");
SysRole role2 = new SysRole();
role2.setRole_name("角色2");
SysRole role3 = new SysRole();
role3.setRole_name("角色3");
user1.getRoles().add(role1);
user1.getRoles().add(role2);
role1.getUsers().add(user1);
role2.getUsers().add(user1);
user2.getRoles().add(role2);
user2.getRoles().add(role3);
role2.getUsers().add(user2);
role3.getUsers().add(user2);
EntityManager em = JPAUtils.getEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
em.persist(user1);
em.persist(user2);
em.persist(role1);
em.persist(role2);
em.persist(role3);
tx.commit();
em.close();
}
如果想级联保存,在User方设置级联保存:
@ManyToMany(cascade=CascadeType.PERSIST)
@JoinTable(name=“user_role”,joinColumns=@JoinColumn(name=“user_id”),inverseJoinColumns=@JoinColumn(name=“role_id”))
private Set roles = new HashSet();
因为设置了级联保存,所以只需要保存用户即可
em.persist(user1);
em.persist(user2);
// em.persist(role1);
// em.persist(role2);
// em.persist(role3);
6.2.2.删除操作
/**
* 测试删除:直接删除用户
* 结果:先删除中间表中与该用户相关的信息,再删除用户
*/
@Test
public void test2(){
EntityManager em = JPAUtils.getEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
SysUser user = em.find(SysUser.class, 1L);
em.remove(user);
tx.commit();
em.close();
}
如果想级联删除,可以在用户一方配置级联删除:
//一个用户对应多个角色
@ManyToMany(cascade=CascadeType.REMOVE)
@JoinTable(name=“user_role”,joinColumns=@JoinColumn(name=“user_id”),inverseJoinColumns=@JoinColumn(name=“role_id”))
private Set roles = new HashSet();
/**
* 测试多对多级联删除:删除用户级联删除角色
*/
@Test
public void test3(){
EntityManager em = JPAUtils.getEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
SysUser user = em.find(SysUser.class, 1L);
em.remove(user);
tx.commit();
em.close();
}
测试发现:报错,原因同xml配置。所以,在多对多中一般不配置级联删除。
6.2.3.修改操作
/**
* 多对多的更新
* 需求:把用户1中的角色1换成角色3
*/
@Test
public void test5(){
EntityManager em = JPAUtils.getEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
//先查询id为1的用户
SysUser user = em.find(SysUser.class, 1L);
//再查询id为1的角色
SysRole role1 = em.find(SysRole.class, 1L);
//再查询id为3的角色
SysRole role3 = em.find(SysRole.class, 3L);
//先移除角色1
user.getRoles().remove(role1);
//在添加角色3
user.getRoles().add(role3);
tx.commit();
em.close();
}
6.3.JPA里的对象导航查询
明确:导航查询的意义和xml的意义一样
6.3.1.查询一方时,延迟加载多方数据
/**
* 查询客户,也要把客户对应的联系人查询出来
*/
@Test
public void test1(){
//获取EntityManager
EntityManager em = JPAUtils.getEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
//查询客户时,延迟加载联系人
Customer customer = em.find(Customer.class, 1L);
Set<LinkMan> linkMans = customer.getLinkMans();
for (LinkMan linkMan : linkMans) {
System.out.println(linkMan);
}
tx.commit();
em.close();
}
6.3.2.查询多方式,立即加载一方数据
/**
* 查询联系人,也要把联系人所属的客户查询出来
*/
@Test
public void test2(){
//获取EntityManager
EntityManager em = JPAUtils.getEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
//查询联系人时,会立即加载客户
LinkMan linkMan = em.find(LinkMan.class, 1L);
Customer customer = linkMan.getCustomer();
System.out.println(customer.getCust_name());
tx.commit();
em.close();
}
提示:如果想改变默认的抓取策略: