spring data jpa

jpa:java persistence api java持久化api

orm思想

  • 操作实体类相当于操作数据库表,不在重点关注sql语句
  • 两个映射:1-实体类和表 2-属性和字段
  • 实现orm思想的框架如:mybatis、hibernate

jpa规范

  • jdbc规范:封装好具体操作数据库接口、方法,只需修改对应驱动
  • 内部由接口和抽象类组成
  • jpa规范不干活,依托实现方式(如:hibernate)来操作。

jpa使用操作

  • 1-jar依赖
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.hibernate.version>5.0.7.Final</project.hibernate.version>
</properties>

<dependencies>
    <!-- junit -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>

    <!-- hibernate对jpa的支持包 -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>${project.hibernate.version}</version>
    </dependency>

    <!-- c3p0 -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-c3p0</artifactId>
        <version>${project.hibernate.version}</version>
    </dependency>

    <!-- log日志 -->
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>

    <!-- Mysql and MariaDB -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.6</version>
    </dependency>

</dependencies>
  • 2-配置文件 需在class目录下的META-INF目录及名称为persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">

    <!--需配置persistence-unit节点
        持久化单元:
            name:持久化单元名称
            transaction-type:事务管理方式   JTA=分布式事务管理   RESOURCE_LOCAL=本地事务管理
    -->
    <persistence-unit name="myJpa" transaction-type="RESOURCE_LOCAL">
        <!--jpa实现方式-->
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

        <properties>
            <!--数据库信息:
                用户名 javax.persistence.jdbc.user
                密码 javax.persistence.jdbc.password
                驱动 javax.persistence.jdbc.driver
                地址 javax.persistence.jdbc.url
            -->
            <property name="javax.persistence.jdbc.user" value="root"></property>
            <property name="javax.persistence.jdbc.password" value="root"></property>
            <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"></property>
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql:///mydb"></property>

            <!--可选配置:配置jpa实现方式的配置信息
                显示sql    true=显示  false=不显示
                自动创建数据库表 :
                    create=程序运行时创建数据库表,有表先删再创建
                    update=程序运行时创建数据库表  有表不会创建
                    none=不会创建数据库表
             -->
            <property name="hibernate.show_sql" value="true"></property>
            <property name="hibernate.hbm2ddl.auto" value="update"></property>
        </properties>
    </persistence-unit>

</persistence>
  • 3-实体类与表映射
package com.xiaoai.domain;

import javax.persistence.*;

/**
 * 客户实体类   需要配置映射关系
 *      1-实体类和表映射
 *      2-属性和字段映射
 *
 *  主键生成策略
 *      IDENTITY=自增   底层必须支持自增      mysql
 *      SEQUENCE=序列   底层必须支持序列      oracle
 *      TABLE=jpa提供的一种机制,通过一张数据库表的形式帮助我们完成主键自增
 *      AUTO=由程序自动帮助我们选择主键生成策略
 */
@Entity   //1-1声明此类为实体类
@Table(name = "mjfs14_customer")   //1-2配置实体类和表映射
public class Customer {

    //2-1配置属性字段映射
    @Id  //声明主键
    @GeneratedValue(strategy = GenerationType.IDENTITY)  //配置主键生成策略  IDENTITY=自增 (要求:底层数据库必须支持自动增长)
    @Column(name = "cust_id")  //对应数据库字段名称
    private Long custId; //客户主键
    @Column(name = "cust_name")
    private String custName;//客户名称
    @Column(name = "cust_source")
    private String custSource;//客户来源
    @Column(name = "cust_level")
    private String custLevel;//客户级别
    @Column(name = "cust_industry")
    private String custIndustry;//客户所属行业
    @Column(name = "cust_phone")
    private String custPhone;//客户联系方式
    @Column(name = "cust_address")
    private String custAddress;//客户地址

    ......对应属性get和set方法以及toString方法

  • 4-具体CRUD操作
    EntityManager相关方法
  • presist(对象) 保存
  • merge(对象) 更新 先查询得到对象,修改对象然后执行修改
  • remove(对象) 删除 先查询得到对象,传入对象进行删除
  • find(待封装对象class,id)/getRefrence(待封装对象class,id) 根据id查询 find立即加载,getRefrence延时加载(懒加载)
package com.xiaoai.test;


import com.sun.xml.internal.txw2.TXW;
import com.xiaoai.domain.Customer;
import com.xiaoai.utils.JpaUtils;
import org.junit.Test;

import javax.persistence.*;

/**
 * jpa相应操作
 *
 * jpa操作步骤:
 *      1-加载配置文件创建工厂(实体管理器工厂)对象
 *          EntityManagerFactory创建过程比较浪费资源
 *          特点:线程安全对象:多个线程访问同一个EntityManagerFactory不会有线程安全问题
 *          ---解决EntityManagerFactory创建过程浪费资源(耗时)问题?
 *          思路:创建公共EntityManagerFactory对象   解决:java中可以使用静态代码块形式创建EntityManagerFactory
 *      2-通过实体管理类工厂获取实体管理器
 *          方法:createEntityManager
 *          内部维护很多内容:数据库信息、缓存信息、所有实体类管理器对象等
 *
 *          createEntityManager对象:实体类管理器   方法:
 *              beginTransaction=创建事务对象
 *              presist=保存
 *              merge=更新
 *              remove=删除
 *              find/getRefrence=根据id查询
 *      3-获取事务对象,开启事务
 *          EntityTransaction 事务对象
 *              begin=开启事务
 *              commit=提交事务
 *              rellback=回滚
 *      4-完成相关增删改查操作
 *      5-提交事务(回滚事务)
 *      6-释放资源
 */
public class JpaTest {

    /**
     *  -----测试jpa的增加 presist
     */
    @Test
    public  void testSave(){
        //1-加载配置文件创建工厂(实体管理器工厂)  根据持久化单元名称创建实体类工厂
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("myJpa");
        //2-获取实体类管理器
        EntityManager em = factory.createEntityManager();
        //3-获取事务管理    打开事务
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        //4-执行操作  增加 presist
        Customer customer = new Customer();
        customer.setCustName("xiaoai");
        customer.setCustIndustry("it");
        em.persist(customer);
        //5-提交事务
        tx.commit();
        //6-释放资源
        em.close();
        factory.close();
    }

    /**
     * -----根据id查询  使用find方法
     *  1-查询对象就是当前待查询对象本身
     *  2-调用find方法时,就会发送sql语句查询数据库
     *
     *  立即加载:得到的即对象本身,调用方法就完成加载
     */
    @Test
    public void testFind(){
        //获取管理器
        EntityManager entityManager = JpaUtils.getEntityManager();  //通过JpaUtils封装生成同一EntityManagerFactory对象,减少资源耗费及耗时
        //获取事务 打开事务
        EntityTransaction tx = entityManager.getTransaction();
        tx.begin();
        //操作
        Customer customer = entityManager.find(Customer.class, 1l);
        System.out.println(customer);
        //提交事务
        tx.commit();
        //关闭  由于使用同一个EntityManagerFactory对象,所以其暂时不能关闭
        entityManager.close();
    }

    /**
     * -----根据id查询  使用getReference方法
     *  1-查询对象是一个动态代理对象
     *  2-不会即时发送sql语句查询数据库,当调用查询结果对象的时候,才会发送查询的sql语句(即什么时候用什么时候发送)
     *  延时加载(懒加载):得到的是一个动态代理对象  什么时候用什么时候加载
     *
     *  一般使用延时加载,
     */
    @Test
    public void testGetReference(){
        //获取管理器
        EntityManager entityManager = JpaUtils.getEntityManager();
        //获取事务 打开事务
        EntityTransaction tx = entityManager.getTransaction();
        tx.begin();
        //操作
        Customer customer = entityManager.getReference(Customer.class, 1l);//getReference
        System.out.println(customer);
        //提交事务
        tx.commit();
        //关闭  由于使用同一个EntityManagerFactory对象,所以其暂时不能关闭
        entityManager.close();
    }

    //-----删除   remove
    @Test
    public void testRemove(){
        //获取管理器
        EntityManager entityManager = JpaUtils.getEntityManager();
        //获取事务 打开事务
        EntityTransaction tx = entityManager.getTransaction();
        tx.begin();
        //操作  删除 先查后删
        //--1-根据id查询客户
        Customer customer = entityManager.find(Customer.class, 1l);//getReference
        //--2-传入所查询结果删除
        entityManager.remove(customer);
        //提交事务
        tx.commit();
        //关闭  由于使用同一个EntityManagerFactory对象,所以其暂时不能关闭
        entityManager.close();
    }

    //-----更新   merge
    @Test
    public void testUpdate(){
        //获取管理器
        EntityManager entityManager = JpaUtils.getEntityManager();
        //获取事务 打开事务
        EntityTransaction tx = entityManager.getTransaction();
        tx.begin();
        //操作  更新  先查询获取对象,修改对象后更新对象
        //--1-根据id查询客户
        Customer customer = entityManager.find(Customer.class, 2l);//getReference
        //--2-修改对象信息
        customer.setCustIndustry("net");
        //--2-传入所查询结果删除
        entityManager.merge(customer);
        //提交事务
        tx.commit();
        //关闭  由于使用同一个EntityManagerFactory对象,所以其暂时不能关闭
        entityManager.close();
    }
}

EntityManagerFactory封装

package com.xiaoai.utils;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

/**
 * 解决实体管理器工厂的浪费资源和耗时问题
 *  通过静态代码块的形式,当程序第一次访问此工具类是,创建一个公共的实体管理器工厂对象
 *
 *  1-第一次访问getEntityManager方法,经静态代码块创建factory对象,再调用方法创建一个EntityManager对象
 *  2-第二次访问getEntityManager方法,直接通过一个已经创建好的factory对象创建EntityManager对象
 */
public class JpaUtils {
    private static EntityManagerFactory factory;

    static {
        //加载配置文件,创建EntityManagerFactory
        factory  = Persistence.createEntityManagerFactory("myJpa");
    }

    /**
     * 用来获取EntityManager对象
     */
    public static EntityManager getEntityManager(){
        return factory.createEntityManager();
    }
}

jpql查询 java persistence query language jpa提供的一种查询语句 和sql差不多

sql:查询的是表和表中的字段
jpql:查询的是实体类和类中属性

步骤:

  • 1-EntityManagerFactory 工厂
  • 2-EntityManager 实体类管理器
  • 3-EntityTransaction 打开事务
  • 4-Query:jpql具体查询语句获取query对象,query对象执行查询 (jpa直接通过EntityManager对象进行操作)
  • 5-提交事务
  • 6-释放资源
package com.xiaoai.test;

import com.xiaoai.utils.JpaUtils;
import org.junit.Test;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.Query;
import java.util.List;

/**
 * jpql查询
 */
public class JpqlTest {

    /**
     * -----查询全部
     *      sql:select * from mjfs14_customer
     *      jqpl:from com.xiaoai.domain.Customer(可以使用全限定类名也可以简写: from Customer)
     */
    @Test
    public void testFindAll(){
        //获取entityManager对象
        EntityManager entityManager = JpaUtils.getEntityManager();
        //开启事务
        EntityTransaction tx = entityManager.getTransaction();
        tx.begin();
        //操作
            //--1获取query对象
            String jpql = "from com.xiaoai.domain.Customer";
            Query query = entityManager.createQuery(jpql);
            //--2具体操作,封装结果集
            List list = query.getResultList();
            for (Object obj:list ) {
                System.out.println(obj);
            }
        //提交事务
        tx.commit();
        //释放资源
        entityManager.close();

        /*结果如下:
        Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from mjfs14_customer customer0_
        Customer{custId=1, custName='xiaoai2', custSource='null', custIndustry='it', custLevel='null', custAddress='null', custPhone='null'}
        Customer{custId=2, custName='xiaoai', custSource='null', custIndustry='net', custLevel='null', custAddress='null', custPhone='null'}
        Customer{custId=3, custName='xiaoai3', custSource='null', custIndustry='无业游民', custLevel='null', custAddress='null', custPhone='null'}
        Customer{custId=4, custName='小艾', custSource='null', custIndustry='教育', custLevel='null', custAddress='null', custPhone='null'}
        */
    }

    /**
     * -----倒叙查询
     *      sql: select * from mjfs14_customer order by cust_id DESC
     *      jpql: from Customer order by custId desc
     */
    @Test
    public void testOrders(){
        //获取entityManager对象
        EntityManager entityManager = JpaUtils.getEntityManager();
        //开启事务
        EntityTransaction tx = entityManager.getTransaction();
        tx.begin();
        //操作
            //--1获取query对象
            String jpql = "from Customer order by custId desc";
            Query query = entityManager.createQuery(jpql);
            //--2具体操作,封装结果集
            List list = query.getResultList();
            for (Object obj:list ) {
                System.out.println(obj);
            }
        //提交事务
        tx.commit();
        //释放资源
        entityManager.close();

        /*结果如下:
        Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from mjfs14_customer customer0_ order by customer0_.cust_id desc
        Customer{custId=4, custName='小艾', custSource='null', custIndustry='教育', custLevel='null', custAddress='null', custPhone='null'}
        Customer{custId=3, custName='xiaoai3', custSource='null', custIndustry='无业游民', custLevel='null', custAddress='null', custPhone='null'}
        Customer{custId=2, custName='xiaoai', custSource='null', custIndustry='net', custLevel='null', custAddress='null', custPhone='null'}
        Customer{custId=1, custName='xiaoai2', custSource='null', custIndustry='it', custLevel='null', custAddress='null', custPhone='null'}
        */
    }

    /**
     * -----统计查询
     *      sql: select count(cust_id) from mjfs14_customer
     *      jpql: select count(custId) from Customer
     */
    @Test
    public void testCount(){
        //获取entityManager对象
        EntityManager entityManager = JpaUtils.getEntityManager();
        //开启事务
        EntityTransaction tx = entityManager.getTransaction();
        tx.begin();
        //操作
            //--1获取query对象
            String jpql = "select count(custId) from Customer";
            Query query = entityManager.createQuery(jpql);
            //--2具体操作,封装结果集
            Object result = query.getSingleResult();//得到唯一的结果集
        System.out.println(result);
        //提交事务
        tx.commit();
        //释放资源
        entityManager.close();

        /*结果如下:
        Hibernate: select count(customer0_.cust_id) as col_0_0_ from mjfs14_customer customer0_
        4
        */
    }

    /**
     * -----分页查询
     *      sql: select * from mjfs14_customer limit ?,?
     *      jpql: from Customer
     */
    @Test
    public void testPaged(){
        //获取entityManager对象
        EntityManager entityManager = JpaUtils.getEntityManager();
        //开启事务
        EntityTransaction tx = entityManager.getTransaction();
        tx.begin();
        //操作
            //--1获取query对象
            String jpql = "from Customer";
            Query query = entityManager.createQuery(jpql);
            //--2具体操作,封装结果集
            //----设置参数(分页参数)
            query.setFirstResult(0);//从下标0开始查
            query.setMaxResults(2);//每次查询两条
            List list = query.getResultList();
            for (Object obj:list ) {
                System.out.println(obj);
            }
        //提交事务
        tx.commit();
        //释放资源
        entityManager.close();

        /*结果如下:
        Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from mjfs14_customer customer0_ limit ?
        Customer{custId=1, custName='xiaoai2', custSource='null', custIndustry='it', custLevel='null', custAddress='null', custPhone='null'}
        Customer{custId=2, custName='xiaoai', custSource='null', custIndustry='net', custLevel='null', custAddress='null', custPhone='null'}
        */
    }

    /**
     * -----条件查询
     *      sql: select * from mjfs14_customer where cust_name like ?
     *      jpql: from Customer where custName like ?
     */
    @Test
    public void testCondition(){
        //获取entityManager对象
        EntityManager entityManager = JpaUtils.getEntityManager();
        //开启事务
        EntityTransaction tx = entityManager.getTransaction();
        tx.begin();
        //操作
            //--1获取query对象
            String jpql = "from Customer where custName like ?";
            Query query = entityManager.createQuery(jpql);
            //--2具体操作,封装结果集
            //----设置参数(占位符参数)
            query.setParameter(1,"xiaoai%");//参数:1=第几个占位符  2=代替值
            List list = query.getResultList();
            for (Object obj:list ) {
                System.out.println(obj);
            }
        //提交事务
        tx.commit();
        //释放资源
        entityManager.close();

        /*结果如下:
        Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from mjfs14_customer customer0_ where customer0_.cust_name like ?
        Customer{custId=1, custName='xiaoai2', custSource='null', custIndustry='it', custLevel='null', custAddress='null', custPhone='null'}
        Customer{custId=2, custName='xiaoai', custSource='null', custIndustry='net', custLevel='null', custAddress='null', custPhone='null'}
        Customer{custId=3, custName='xiaoai3', custSource='null', custIndustry='无业游民', custLevel='null', custAddress='null', custPhone='null'}
        */
    }
}

spring data jpa

相互关系:我们写的java代码——》spring data jpa——》jpa规范——》hibernate(封装jdbc)——》数据库

基础使用

  • 导入jar
<properties>
    <spring.version>4.2.4.RELEASE</spring.version>
    <hibernate.version>5.0.7.Final</hibernate.version>
    <slf4j.version>1.6.6</slf4j.version>
    <log4j.version>1.2.12</log4j.version>
    <c3p0.version>0.9.1.2</c3p0.version>
    <mysql.version>5.1.6</mysql.version>
</properties>

<dependencies>
    <!-- junit单元测试 -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.9</version>
        <scope>test</scope>
    </dependency>

    <!-- spring beg -->
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.6.8</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-orm</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!-- spring end -->

    <!-- hibernate beg -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>${hibernate.version}</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>${hibernate.version}</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>5.2.1.Final</version>
    </dependency>
    <!-- hibernate end -->

    <!-- c3p0 beg -->
    <dependency>
        <groupId>c3p0</groupId>
        <artifactId>c3p0</artifactId>
        <version>${c3p0.version}</version>
    </dependency>
    <!-- c3p0 end -->

    <!-- log end -->
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>${log4j.version}</version>
    </dependency>

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>${slf4j.version}</version>
    </dependency>

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>${slf4j.version}</version>
    </dependency>
    <!-- log end -->


    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>${mysql.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-jpa</artifactId>
        <version>1.9.0.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>4.2.4.RELEASE</version>
    </dependency>

    <!-- el beg 使用spring data jpa 必须引入 -->
    <dependency>
        <groupId>javax.el</groupId>
        <artifactId>javax.el-api</artifactId>
        <version>2.2.4</version>
    </dependency>

    <dependency>
        <groupId>org.glassfish.web</groupId>
        <artifactId>javax.el</artifactId>
        <version>2.2.4</version>
    </dependency>
    <!-- el end -->
</dependencies>
  • 配置spring配置文件(配置spring data jpa整合)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:task="http://www.springframework.org/schema/task"
       xsi:schemaLocation="
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
		http://www.springframework.org/schema/data/jpa
		http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">

    <!--spring 和 spring data jpa的配置-->
    <!--1==创建entityManagerFactory对象-->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource"></property><!--数据源-->
        <property name="packagesToScan" value="com.xiaoai.domain"></property><!--扫描实体类所在包-->
        <property name="persistenceProvider">
            <bean class="org.hibernate.jpa.HibernatePersistenceProvider"></bean><!--配置jpa的实现厂家-->
        </property>
        <!--JPA的供应商适配器-->
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <!--配置是否自动创建数据库表-->
                <property name="generateDdl" value="false" /><!--是否自动创建表-->
                <property name="database" value="MYSQL" /> <!--数据库类型-->
                <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" /><!--数据库方言:数据库支持的特有语法-->
                <property name="showSql" value="true" /><!--是否显示sql语句:即是否打印到控制台-->
            </bean>
        </property>
        <!--jpa方言,高级特性-->
        <property name="jpaDialect">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"></bean>
        </property>
    </bean>
    <!--2=创建数据库连接池-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="user" value="root"></property>
        <property name="password" value="root"></property>
        <property name="jdbcUrl" value="jdbc:mysql:///mydb?useUnicode=true&amp;characterEncoding=UTF-8"></property>
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
    </bean>
    <!--3=整合spring dataJpa-->
    <jpa:repositories base-package="com.xiaoai.dao"
                      transaction-manager-ref="transactionManager"
                        entity-manager-factory-ref="entityManagerFactory">
    </jpa:repositories>

    <!--4=配置事务管理器-->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"></property>
    </bean>

    <!--5=spring声明式事务-->
    <!--6=配置包扫描-->
    <context:component-scan base-package="com.xiaoai"></context:component-scan>
</beans>
  • 编写实体类及映射 同jpa一致
  • 编写dao层
    • 只要编写dao接口,不需编写实现类
    • 接口需继承两接口:JpaRepository, JpaSpecificationExecutor 接口需提供响应泛型
      • JpaRepository<操作的实体类类型,实体类类型主键属性的类型> 封装了基本curd操作
      • JpaSpecificationExecutor<操作的实体类类型> 封装了复杂查询(分页等)
package com.xiaoai.dao;

import com.xiaoai.domain.Customer;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;

public interface CustomerDao extends JpaRepository<Customer,Long>,JpaSpecificationExecutor<Customer> {

}
  • 注入接口对象,直接使用

接口相关方法

  • findOne(id) 根据id查询
  • save(对象) 对象标识主键 不存在=新增 存在=修改(修改需要先查询然后修改,不要直接创建相同id的对象然后直接执行修改)
  • delete(id) 根据id删除
  • findAll() 查询所有
  • count() 统计总数量
  • exists(id) 查询id为xx的数据是否存在
    • 思路1:查询id为xx数据,判断值是否为空
    • 思路2:判断id为xx的数据数量,数量为0即不存在 JPA即是该种思路
  • getOne(id) 根据id查询 测试方法上需要 @Transactional支持
    • 与findOne区别:findOne底层调用entityManager的find()方法即立即加载,GetOne底层调用entityManager的getRefrence()方法即延时加载。为了延时加载正常执行需要加上事务支持
package com.xiaoai.test;

import com.xiaoai.dao.CustomerDao;
import com.xiaoai.domain.Customer;
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 org.springframework.transaction.annotation.Transactional;

import java.util.List;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class CustomerDaoTest {

    @Autowired
    CustomerDao customerDao;

    /**
     * -----根据id查询
     */
    @Test
    public void testFindOne(){
        Customer one = customerDao.findOne(3l);
        System.out.println(one);

        /*结果
        Hibernate: select customer0_.cust_id as cust_id1_0_0_, customer0_.cust_address as cust_add2_0_0_, customer0_.cust_industry as cust_ind3_0_0_, customer0_.cust_level as cust_lev4_0_0_, customer0_.cust_name as cust_nam5_0_0_, customer0_.cust_phone as cust_pho6_0_0_, customer0_.cust_source as cust_sou7_0_0_ from mjfs14_customer customer0_ where customer0_.cust_id=?
        Customer{custId=3, custName='xiaoai3', custSource='null', custIndustry='无业游民', custLevel='null', custAddress='null', custPhone='null'}
        */
    }
    /**
     * -----save:保存或者更新,根据传入的对象主键id是否存在判断新增或更新
     */
    @Test
    public void testSave(){
        //新增
        Customer customer = new Customer();
        customer.setCustName("程序员");
        customer.setCustLevel("3");
        customer.setCustIndustry("it");
        customerDao.save(customer);
    }
    /**
     * -----save:保存或者更新,根据传入的对象主键id是否存在判断新增或更新
     */
    @Test
    public void testUpdate(){
//        Customer customer = new Customer();
//        customer.setCustId(5l); //id为5的数据已经存在,
//        customer.setCustName("程序员");
//        customerDao.save(customer);
        //如果像上面那样修改,则id为5的数据名称改为了程序员,但其他属性将变为空。
        // 因为修改是查询然后修改,这里直接定义了新对象设置了名称其他属性都为空,即用其替换了原来的5号数据
        //应该先查询获得对象,然后修改对象再执行修改。
        Customer customer = customerDao.findOne(5l);
        customer.setCustName("程序员");//修改编号5数据的名称为程序员
        customerDao.save(customer);
    }
     /**
     * -----删除
     */
    @Test
    public void testDelete(){
        customerDao.delete(6l);
    }
    /**
     * -----查询所有
     */
    @Test
    public void testFindAll(){
        List<Customer> all = customerDao.findAll();
        for (Customer c : all) {
            System.out.println(c);
        }
        /* 测试结果:
        Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from mjfs14_customer customer0_
        Customer{custId=1, custName='xiaoai2', custSource='null', custIndustry='it', custLevel='null', custAddress='null', custPhone='null'}
        Customer{custId=2, custName='xiaoai', custSource='null', custIndustry='net', custLevel='null', custAddress='null', custPhone='null'}
        Customer{custId=3, custName='xiaoai3', custSource='null', custIndustry='无业游民', custLevel='null', custAddress='null', custPhone='null'}
        Customer{custId=4, custName='小艾', custSource='null', custIndustry='教育', custLevel='null', custAddress='null', custPhone='null'}
        Customer{custId=5, custName='程序员', custSource='null', custIndustry='it', custLevel='3', custAddress='null', custPhone='null'}
        */

    }
    /**
     *-----统计查询
     */
    @Test
    public void testCount(){
        long count = customerDao.count();
        System.out.println(count);
        /*测试结果:
        Hibernate: select count(*) as col_0_0_ from mjfs14_customer customer0_
        5
        */
    }
    /**
     * -----判断数据是否存在
     */
    @Test
    public void testExists(){
        boolean exists = customerDao.exists(4l);
        System.out.println("是否存在:"+exists);
        /*测试结果:
        Hibernate: select count(*) as col_0_0_ from mjfs14_customer customer0_ where customer0_.cust_id=? and 1=1
        是否存在:true
        */
    }
    /**
     * -----根据id查询
     */
    @Test
    @Transactional  //保证getOne正常运行
    public void testGetOne(){
        Customer one = customerDao.getOne(4l);
        System.out.println(one);
        /*测试结果:
        Hibernate: select customer0_.cust_id as cust_id1_0_0_, customer0_.cust_address as cust_add2_0_0_, customer0_.cust_industry as cust_ind3_0_0_, customer0_.cust_level as cust_lev4_0_0_, customer0_.cust_name as cust_nam5_0_0_, customer0_.cust_phone as cust_pho6_0_0_, customer0_.cust_source as cust_sou7_0_0_ from mjfs14_customer customer0_ where customer0_.cust_id=?
        Customer{custId=4, custName='小艾', custSource='null', custIndustry='教育', custLevel='null', custAddress='null', custPhone='null'}
        */
    }
}

定义jpql/sql语句查询

  • 特有查询:需要在dao接口上配置方法
  • 新添加的方法上使用注解形式配置jpql语句
  • 注解:@query
    • 注解属性value=jpql语句或sql语句
    • 注解属性nativeQuery=false(使用jqpl查询)或true(使用本地查询:即sql查询)
  • jpql更深层封装:只需要按照springDataJpa提供的方法名称规则定义方法,不需要去配置jpql语句,也可以完成查询
    • findBy+属性名称() = 查询 如:findByCustName 根据方法名称(findBy)解析要查询 from 实体类 where 属性名称(如custName) = 参数
    • findBy+属性名称+查询方式(like、isnull) 如:findByCustNameLike
    • findBy+属性名+查询方式+多条件连接符(and、or)+属性名+查询方式(精准匹配可以省略查询方式) 如:findByCustNameLikeAndCustIndustry
      接口定义的方法
package com.xiaoai.dao;

import com.xiaoai.domain.Customer;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;

import java.util.List;

/**
 * 定义符合springdataJpa的dao层接口规范
 *      JpaRepository<操作的实体类类型,实体类类型主键属性的类型>
 *          封装了基本curd操作
 *     JpaSpecificationExecutor<操作的实体类类型>
 *         封装了复杂查询(分页)
 */
public interface CustomerDao extends JpaRepository<Customer,Long>,JpaSpecificationExecutor<Customer> {

    //===============================================================自定义jpql执行方法
    //使用注解@Query

    //-----根据客户名称查询客户
    @Query(value = "from Customer where custName=?")
    public Customer jpqlFindByName(String custName);

    //-----根据客户名称id查询客户
    // 需要注意多占位符的匹配关系问题
    // 默认情况下,占位符位置需要和方法参数中位置保持一致
    // 但也可以指定占位符参数位置:通过【?索引】的方式指定此占位符的取值来源 如?1 表示该占位符取方法第一个参数
    @Query(value = "from Customer where custName=?1 and custId=?2")
    public Customer jpqlFindByNameAndId(String name,Long id);

    //-----根据id更新客户名称
    @Query(value = "update Customer set custName=?2 where custId=?1")
    @Modifying //声明此方法是用来进行更新操作
    public void jpqlUpdateNameById(Long custId,String custName);

    //===============================================================自定义sql语句执行方法
    // @Query  属性:value=jpql语句或sql语句   nativeQuery=false(使用jqpl查询)或true(使用本地查询:即使用sql查询)

    //-----查询所有
    @Query(value = "select * from mjfs14_customer",nativeQuery = true)
    public List<Object[]> findSql();

    //-----根据名称模糊查询
    @Query(value = "select * from mjfs14_customer where cust_name like ?1",nativeQuery = true)
    public List<Object[]> findSqlByName(String name);

    //===============================================================jpql的深层封装:根据springDataJpa提供的命名方法
    // findByXxx = 查询  Xxx即对象属性即查询条件  如:findByCustName   根据方法名称(findBy)解析要查询 from 实体类 where xxx(属性名称如custName) = 参数

    //-----根据名称查询
    public Customer findByCustName(String custName);

    //-----根据名称模糊查询
    public List<Customer> findByCustNameLike(String custName);

    //-----查询客户名模糊匹配和客户所属行业精准匹配
    public List<Customer> findByCustNameLikeAndCustIndustry(String custName,String custIndustry);

}

测试

package com.xiaoai.test;

import com.xiaoai.dao.CustomerDao;
import com.xiaoai.domain.Customer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;

import javax.management.Query;
import java.util.Arrays;
import java.util.List;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class JpqlTest {

    @Autowired
    CustomerDao customerDao;

    //-----自定义jpql:根据名称查询
    @Test
    public void testJpqlFindByName(){
        Customer customer = customerDao.jpqlFindByName("xiaoai");
        System.out.println(customer);
        /* 执行结果:
        Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from mjfs14_customer customer0_ where customer0_.cust_name=?
        Customer{custId=2, custName='xiaoai', custSource='null', custIndustry='net', custLevel='null', custAddress='null', custPhone='null'}
        */
    }
    //-----自定义jpql:根据名称和id查询
    @Test
    public void testJpqlFindByNameAndId(){
        Customer customer = customerDao.jpqlFindByNameAndId("xiaoai",2l);
        System.out.println(customer);
        /* 执行结果:
        Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from mjfs14_customer customer0_ where customer0_.cust_name=? and customer0_.cust_id=?
        Customer{custId=2, custName='xiaoai', custSource='null', custIndustry='net', custLevel='null', custAddress='null', custPhone='null'}
        */
    }
    //-----自定义jpql:根据id更新客户名称
    @Test
    @Transactional //spring data jpa 使用jpql完成更新、删除操作需要手动添加事务支持 执行结束后其会自动回滚事务
    @Rollback(value = false) //设置不自动回滚
    public void testJpqlUpdateNameById(){
       customerDao.jpqlUpdateNameById(3l,"程序员小艾");
        Customer customer = customerDao.findOne(3l);
        System.out.println(customer);
        /* 执行结果:
        Hibernate: update mjfs14_customer set cust_name=? where cust_id=?
        Hibernate: select customer0_.cust_id as cust_id1_0_0_, customer0_.cust_address as cust_add2_0_0_, customer0_.cust_industry as cust_ind3_0_0_, customer0_.cust_level as cust_lev4_0_0_, customer0_.cust_name as cust_nam5_0_0_, customer0_.cust_phone as cust_pho6_0_0_, customer0_.cust_source as cust_sou7_0_0_ from mjfs14_customer customer0_ where customer0_.cust_id=?
        Customer{custId=3, custName='程序员小艾', custSource='null', custIndustry='无业游民', custLevel='null', custAddress='null', custPhone='null'}
        */
    }

    //-----自定义sql:查询所有
    @Test
    public void testFindSql(){
        List<Object[]> list = customerDao.findSql();
        for (Object[] obj : list) {
            System.out.println(Arrays.toString(obj));
        }
        /* 执行结果:
        Hibernate: select * from mjfs14_customer
        [1, xiaoai2, null, it, null, null, null]
        [2, xiaoai, null, net, null, null, null]
        [3, 程序员小艾, null, 无业游民, null, null, null]
        [4, 小艾, null, 教育, null, null, null]
        [5, 程序员, null, it, 3, null, null]
        */
    }
     //-----自定义sql:根据名称模糊查询
    @Test
    public void testFindSqlByName(){
        List<Object[]> list = customerDao.findSqlByName("xiaoai%");
        for (Object[] obj : list) {
            System.out.println(Arrays.toString(obj));
        }
        /* 执行结果:
        Hibernate: select * from mjfs14_customer where cust_name like ?
        [1, xiaoai2, null, it, null, null, null]
        [2, xiaoai, null, net, null, null, null]
        */
    }

    //-----jpql进一步封装:根据名称查询
    @Test
    public void testFindByName(){
        Customer customer = customerDao.findByCustName("小艾");
        System.out.println(customer);
        /* 执行结果:
        Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from mjfs14_customer customer0_ where customer0_.cust_name=?
        Customer{custId=4, custName='小艾', custSource='null', custIndustry='教育', custLevel='null', custAddress='null', custPhone='null'}
        */
    }
    //-----jpql进一步封装:根据名称模糊查询
    @Test
    public void testFindByNameLike(){
        List<Customer> customers = customerDao.findByCustNameLike("xiaoai%");
        for (Customer c : customers) {
            System.out.println(c);
        }
        /* 执行结果:
        Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from mjfs14_customer customer0_ where customer0_.cust_name like ?
        Customer{custId=1, custName='xiaoai2', custSource='null', custIndustry='it', custLevel='null', custAddress='null', custPhone='null'}
        Customer{custId=2, custName='xiaoai', custSource='null', custIndustry='net', custLevel='null', custAddress='null', custPhone='null'}
        */
    }
    //-----jpql进一步封装:客户名模糊匹配和客户所属行业精准匹配
    @Test
    public void testFindByNAndI(){
        List<Customer> customers = customerDao.findByCustNameLikeAndCustIndustry("xiaoai%","it");
        for (Customer c : customers) {
            System.out.println(c);
        }
        /* 执行结果:
        Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from mjfs14_customer customer0_ where (customer0_.cust_name like ?) and customer0_.cust_industry=?
        Customer{custId=1, custName='xiaoai2', custSource='null', custIndustry='it', custLevel='null', custAddress='null', custPhone='null'}
        */
    }
}

specifications动态查询

Specification即查询条件
即接口继承的JpaSpecificationExecutor类所提供的方法列表:

  • T findOne(Specification var1); 单个查询
  • List findAll(Specification var1); 查询列表
  • Page findAll(Specification var1, Pageable var2); 分页查询 pageable=分页参数
  • List findAll(Specification var1, Sort var2); 查询列表 sort=排序参数
  • long count(Specification var1); 统计查询

**使用**

  • 创建Specification对象,通过匿名内部类构建查询条件,再把对象传入JpaSpecificationExecutor提供的方法中完成查询
    • 匿名内部类方法参数:Root 获取查询的对象属性 get()=获取属性
    • 匿名内部类方法参数:CriteriaBuilder 用于构建条件 .equal()=精准查询 .like()=模糊查询 .and()=连接属性
  • equal:直接得到path对象,然后进行比较
  • gt,lt,ge,le,like:得到path对象,根据path指定比较的参数类型,再去进行比较 指定参数类型格式:path对象.as(类型字节码对象) 如: Predicate like = criteriaBuilder.like(custName.as(String.class), "xiaoai%");
  • 排序:创建排序对象做参数传入对应方法 Sort sort = new Sort(Sort.Direction.DESC,"custId");//倒序
  • 分页:创建分页对象做参数传入对应方法
@Test
public void testSpec5(){
    //添加分页
    Pageable pageable = new PageRequest(0,3); //创建分页对象 参数:1=当前查询的页数(从0开始) 2=每页查询数量
    Page<Customer> pageCustomer = customerDao.findAll(null, pageable);//Specification传入空,表示查询全部
    System.out.println("总条数:"+pageCustomer.getTotalElements());
    System.out.println("总页数:"+pageCustomer.getTotalPages());
    List<Customer> content = pageCustomer.getContent();//获取当前页数据列表
    for (Customer c : content) {
        System.out.println(c);
    }

    /*执行结果:
    Hibernate: select count(customer0_.cust_id) as col_0_0_ from mjfs14_customer customer0_
    Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from mjfs14_customer customer0_ limit ?
    总条数:5
    总页数:2
    Customer{custId=1, custName='xiaoai2', custSource='null', custIndustry='it', custLevel='null', custAddress='null', custPhone='null'}
    Customer{custId=2, custName='xiaoai', custSource='null', custIndustry='net', custLevel='null', custAddress='null', custPhone='null'}
    Customer{custId=3, custName='程序员小艾', custSource='null', custIndustry='无业游民', custLevel='null', custAddress='null', custPhone='null'}
    */
}

多表操作

一对多

  • 主要是配置实体类映射时和其他实体类的关系
    • 一对一
    • 一对多、多对一 注:在一的一方维护外键即可,不需要一和多都维护外键
    • 多对多
  • 可以添加实体类属性并配置其关系映射可完成多表操作
    • 配置相互关系可用实体类间的包含关系,即在实体类中添加另一个实体类作为属性。并需要配置其关系:1-声明表关系 2-配置外键
多的一方:
@OneToMany(targetEntity = LinkMan.class)  //配置一对多关系  需对方字节码对象
@JoinColumn(name = "lkm_cust_id",referencedColumnName = "cust_id")  //name=从表的外键字段,referencedColumnName=主表的主键字段
private Set<LinkMan> linkmans = new HashSet<>();

一的一方:
//配置联系人到客户多对一关系   1-声明表关系  2-配置外键
@ManyToOne(targetEntity = Customer.class)
@JoinColumn(name = "lkm_cust_id",referencedColumnName = "cust_id") //name=从表的外键字段,referencedColumnName=本表的主键字段
private Customer customer;

多的一方放弃维护外键:mappedBy="对方配置关系的属性名" 
@OneToMany(mappedBy="customer")
private Set<LinkMan> linkmans = new HashSet<>();  //放弃外键维护权,表关系交给一的一方维护

  • 一对多删除:删除【一一方】需要考虑,因为有可能【多一方】引入了【一一方】 在【一一方】删除时则需要使用级联删除
    • 级联:操作一个对象的同时操作他的关联对象
    • 级联删除:删除【一一方】的同时删除关联其的【多一方】的所有数据。想级联删除需要在操作的主体即【一一方】的实体类上添加级联属性(配置级联:cascade)
配置级联:
@OneToMany(mappedBy="customer",cascade = CascadeType.ALL) //CascadeType.ALL=所有操作(insert、delete等)都可级联
private Set<LinkMan> linkmans = new HashSet<>();

多对多

  • 创建实体类配置映射,通过包含关系加入另一实体类做属性,配置实体类间多对多关系
//建立关联   1-声明表关系   2-配置中间表(包含两个外键)
@ManyToMany(targetEntity = Role.class)
@JoinTable(name = "mjfs14_user_role", //中间表名称     @JoinColumn和@inverseJoinColumns参数:name=对应外键字段  referencedColumnName=对应主键字段
        joinColumns = {@JoinColumn(name = "center_user_id",referencedColumnName = "user_id")}, // 当前对象在中间表中对应外键配置
        inverseJoinColumns = {@JoinColumn(name = "center_role_id",referencedColumnName = "role_id")} //对方对象在中间表中对应外键配置
)
private Set<Role> roles = new HashSet<>();
  • 放弃外键维护权:两方都是多,随便一方都可以放弃外键维护权 但是一般被选择一方放弃 放弃维护权和【一对多】一致
  • 级联操作:删除对象以及对象关联的对象以及中间表中关联的数据 操作和一对多一致

对象导航查询

  • 查询一个对象时,通过此对象查询其关联对象 操作即:直接通过对象.getxxx()方法即之前创建关联的对象属性时的get方法获取即可 内部自动查询好了
  • 一方查询多方:默认使用延迟加载(因为在一方查询多方,有可能多方有太多数据,立即加载后不用则极大浪费内存) 多方查询一方:默认使用立即加载(多方查询一方时由于只多一条数据,影响不大,所以立即查询了)
  • 延迟加载: 默认即使用延迟加载的形式查询的 可以修改延迟加载为立即加载 即在实体类映射中通过@OneToMany属性fetch配置 EAGER=立即加载 LAZY=延迟加载
配置立即加载:
//使用注解形式配置多表关系  1-声明关系  2-配置外键
@OneToMany(mappedBy="customer",cascade = CascadeType.ALL,fetch = FetchType.EAGER ) //CascadeType.ALL=所有操作(insert、delete等)都可级联  FetchType.EAGER
private Set<LinkMan> linkmans = new HashSet<>();
原文地址:https://www.cnblogs.com/xiaoaiying/p/13566310.html