Hibernate第四天

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();
}

提示:如果想改变默认的抓取策略:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值