JPA初始

以下内容引用尚硅谷,如有侵权请联系删除

第一章 JPA概述

![在这里插入图片描述]( https://img-blog.csdnimg.cn/146805ab58864e2babd57c210cdd3160.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/de0745a87ead41a29b92ba907d8cd98c.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/0d19a0342d0f48ed898b4f7fe37cf59b.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/62d63fddf9094d089a107b0077b97d67.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/cd983f05a248490dacf6650a428b3332.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/5da76816610d4584b9bb3567a5a64468.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

第二章 JPA基本注解

2.1 @Entity

@Entity标注用于实体类声明语句之前,指出该Java类为实体类,将映射到指定的数据库表。如声明一个实体类Customer,它将映射到数据库中的customer表上。

2.2 @Table

当实体类与其映射的数据库表名不同名时需要使用@Table标注说明,该标注与@Entity标注并列使用,置于实体类声明语句之前,可写于单独语句行,也可与声明语句同行。

@Table标注的常用选项是name,用于指明数据库的表名@Table标注还有一个两个选项catalog和schema用于设置表所属的数据库目录或模式,通常为数据库名。

uniqueConstraints选项用于设置约束条件,通常不须设置。

2.3 @Id

@Id标注用于声明一个实体类的属性映射为数据库的主键列。该属性通常置于属性声明语句之前,可与声明语句同行,也可写在单独行上。

@Id标注也可置于属性的getter方法之前。

@GeneratedValue
![在这里插入图片描述]( https://img-blog.csdnimg.cn/519d9d1231644d3f9f48c3de5618b064.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

2.4 @Basic

![在这里插入图片描述]( https://img-blog.csdnimg.cn/496e733ede45458eaf29c90a6c603834.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

2.5 @Column

![在这里插入图片描述]( https://img-blog.csdnimg.cn/b7018f4198fa4485913889fe681cdd16.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
@Transient
表示该属性并非一个到数据库表的字段的映射,ORM框架将忽略该属性.

如果一个属性并非数据库表的字段映射,就务必将其标示为Transient,否则,ORM框架默认其注解为@Basic

@Temporal
在核心的Java API中并没有定义Date类型的精度(temporal precision).而在数据库中,表示Date类型的数据有DATE, TIME,和TIMESTAMP三种精度(即单纯的日期,时间,或者两者兼备).在进行属性映射时可使用
@Temporal注解来调整精度.

2.6 用table来生成主键详解

![在这里插入图片描述]( https://img-blog.csdnimg.cn/eb5651c081e64657bd626c626288e8ee.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/0f964364d70f403ea0ab099ede476022.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

第三章 JPA API

3.1 Persistence

![在这里插入图片描述]( https://img-blog.csdnimg.cn/0d799683eae34fd2bc2e3e49e4f00e5a.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

3.2 EntityManagerFactory

![在这里插入图片描述]( https://img-blog.csdnimg.cn/6c84a2ec64264d5992351e084771229f.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

3.3 EntityManager

![在这里插入图片描述]( https://img-blog.csdnimg.cn/2cf0620a18304353a8c1a1876e99af05.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/907a34cdd4ef4cf48cd883a6e2ad74ea.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/1a35c31c2fc3437487a5f1de13b72a29.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
在这里插入图片描述
![在这里插入图片描述]( https://img-blog.csdnimg.cn/eef2a0bf217b4bc89333785b3dce7b9d.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/e9290551c36b494a86443068c7ea5ea4.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/ab6eda6a22494c0981912d6c75573bd1.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/d4bada50f0e548feb3b0510f9b7b5489.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

3.4 EntityTransaction

EntityTransaction接口用来管理资源层实体管理器的事务操作。
通过调用实体管理器的getTransaction方法获得其实例。
![在这里插入图片描述]( https://img-blog.csdnimg.cn/2df57f9d03fa415881687caedc84e663.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/8ca9e38fa5874a3dba5e7455b0b93b66.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

第四章 映射关联关系

4.1 双向一对多及多对一映射

![在这里插入图片描述]( https://img-blog.csdnimg.cn/044ff2d9b28743ae821e45cf3c143a92.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

4.2 双向一对一映射

![在这里插入图片描述]( https://img-blog.csdnimg.cn/b95612ad8c4a445e9c2b810a24794734.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

4.3 双向1-1不延迟加载的问题

通过Manager查询Department,不管Manager的Department属性上的@OneToOne注解上有没有延迟加载属性,都不管用的,因为外键字段是定义在Department表中的
![在这里插入图片描述]( https://img-blog.csdnimg.cn/99d2cc11c35d4c6ba04ce310c41873b5.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

4.4 双向多对多关联关系

![在这里插入图片描述]( https://img-blog.csdnimg.cn/36d28a080c74440ea6c9017692c99884.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

第四章 代码总结

![在这里插入图片描述]( https://img-blog.csdnimg.cn/8c13de83e03243e19cc6df1d52844773.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
JPA规范要求在类路径的META-INF目录下放置persistence.xml,文件的名称是固定的

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>groupId</groupId>
    <artifactId>jpa-1</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>4.2.4.Final</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.4</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.2</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-c3p0</artifactId>
            <version>4.2.5.Final</version>
        </dependency>
        <!--  jpa-hibernate 依赖 -->
        <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-entitymanager -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>4.2.4.Final</version>
        </dependency>
    </dependencies>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">

    <persistence-unit name="NewPersistenceUnit">
        <!--
          配置使用什么ORM产品来作为JPA的实现
          1.实际上配置的是javax.persistence.spi.PersistenceProvider接口的实现类
          2.若JPA项目中只有一个JPA的实现产品,则也可以不配置该节点。
        -->
        <provider>org.hibernate.ejb.HibernatePersistence</provider>

        <!--添加持久化类-->
        <class>com.atguigu.jpa.helloworld.Customer</class>
        <class>com.atguigu.jpa.helloworld.Order</class>

        <properties>
            <!--连接数据库的基本信息-->
            <property name="hibernate.connection.url" value="jdbc:mysql://172.16.19.104:3306/jpa1"/>
            <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
            <property name="hibernate.connection.username" value="springcloud"/>
            <property name="hibernate.connection.password" value="springcloud"/>

            <!-- 配置JPA实现产品的基本属性,配置hibernate的基本属性-->
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.hbm2ddl.auto" value="update"/>
        </properties>
    </persistence-unit>
</persistence>

package com.atguigu.jpa.helloworld;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import java.util.Date;

@Table(name = "JAP_CUSTOMERS")
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Customer {

    @Id
    //@GeneratedValue(strategy = GenerationType.AUTO)
    @TableGenerator(name = "ID_GENERATOR",
                    table = "jpa_id_generators",
                    pkColumnName = "PK_NAME",
                    pkColumnValue = "CUSTOMER_ID",
                    valueColumnName = "PK_VALUE",
                    allocationSize = 100)
    @GeneratedValue(strategy = GenerationType.TABLE,generator = "ID_GENERATOR")
    private Integer id;

    @Column(name = "LAST_NAME")
    private String lastName;

    private String email;

    private int age;

    @Temporal(TemporalType.TIMESTAMP)
    private Date createdTime;

    @Temporal(TemporalType.DATE)
    private Date birth;

    //工具方法,不需要映射为数据表的一列
    @Transient
    public String getInfo() {
        return "lastName:"+lastName+", email:"+email;
    }

    @Override
    public String toString() {
        return "Customer{" +
                "id=" + id +
                ", lastName='" + lastName + '\'' +
                ", email='" + email + '\'' +
                ", age=" + age +
                ", createdTime=" + createdTime +
                ", birth=" + birth +
                '}';
    }
}

package com.atguigu.jpa.helloworld;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Table(name = "JPA_ORDERS")
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Order {

    @Id
    @GeneratedValue
    private Integer id;

    @Column(name = "ORDER_NAME")
    private String orderName;

    /**
     * 映射单项n-1关联关系
     * 使用@ManyToOne来映射多对一的关联关系
     * 使用@JoinColumn来映射外键
     * 可使用@ManyToOne的fetch属性来修改默认的关联属性的加载策略
     */
    @JoinColumn(name = "CUSTOMER_ID")
    @ManyToOne(fetch = FetchType.LAZY)
    private Customer customer;

}

4.1 HelloWorld

import com.atguigu.jpa.helloworld.Customer;
import org.junit.Test;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.Date;

public class JpaTestOne {

    @Test
    public void test() {
        //1. 创建EntityManagerFactory
        EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("NewPersistenceUnit");

        //2. 创建EntityManager
        EntityManager entityManager = entityManagerFactory.createEntityManager();

        //3. 开启事务
        EntityTransaction transaction = entityManager.getTransaction();
        transaction.begin();

        //4. 进行持久化操作
        Customer customer = new Customer();
        customer.setAge(12);
        customer.setEmail("123@qq.com");
        customer.setLastName("Tom");
        customer.setBirth(new Date());
        customer.setCreatedTime(new Date());

        entityManager.persist(customer);

        //5. 提交事务
        transaction.commit();

        //6. 关闭EntityManager
        entityManager.close();

        //7. 关闭EntityManagerFactory
        entityManagerFactory.close();
    }

}

4.2 常用API

import com.atguigu.jpa.helloworld.Customer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.Date;

public class JpaTestTwo {

    private EntityManagerFactory entityManagerFactory;
    private EntityManager entityManager;
    private EntityTransaction entityTransaction;

    @Before
    public void init() {
        //1. 创建EntityManagerFactory
        entityManagerFactory = Persistence.createEntityManagerFactory("NewPersistenceUnit");

        //2. 创建EntityManager
        entityManager = entityManagerFactory.createEntityManager();

        //3. 开启事务
        entityTransaction = entityManager.getTransaction();
        entityTransaction.begin();
    }

    @After
    public void destory() {
        entityTransaction.commit();
        entityManager.close();
        entityManagerFactory.close();
    }

    /**
     * 类似于hibernate中session的get方法
     */
    @Test
    public void testFind() {
        Customer customer = entityManager.find(Customer.class, 1);
        System.out.println("------------------------------------------------");
        System.out.println(customer);
    }

    /**
     * 类似于hibernate中Session的load方法
     */
    @Test
    public void testGetReference() {
        Customer customer = entityManager.getReference(Customer.class, 1);
        System.out.println(customer.getClass().getName());

        System.out.println("------------------------------------------------");
        System.out.println(customer);
    }

    /**
     * 类似于hibernate的save方法,使对象由临时状态变为持久化状态
     * 和hibernate的save方法的不同之处;若对象有id,则不能执行insert操作,而会抛出异常
     */
    @Test
    public void testPersistence() {
        Customer customer = new Customer();
        customer.setAge(15);
        customer.setBirth(new Date());
        customer.setCreatedTime(new Date());
        customer.setEmail("bb@163.com");
        customer.setLastName("BB");
        customer.setId(100);

        entityManager.persist(customer);
        System.out.println(customer.getId());
    }

    /**
     * 类似于hibernate中Session的delete方法,把对象对应的记录从数据库中移除
     * 但注意:该方法只能移除持久化对象,而hibernate的delete方法实际上还可以移除游离对象
     */
    @Test
    public void testRemove() {
        //Customer customer = new Customer();
        //customer.setId(2);

        Customer customer = entityManager.find(Customer.class, 2);
        entityManager.remove(customer);
    }

    /**
     * 总的来说,类似于hibernate Session的saveOrUpdate方法
     */
    /**
     * 1.若传入的是一个临时对象
     * 会创建一个新的对象,把临时对象的属性复制到新的对象中,然后对新的对象执行持久化操作,所以
     * 新的对象中有id,但以前的临时对象中没有id
     */
    @Test
    public void testMergeOne() {
        Customer customer = new Customer();
        customer.setAge(18);
        customer.setBirth(new Date());
        customer.setEmail("cc@163.com");
        customer.setLastName("CC");

        Customer customer2 = entityManager.merge(customer);

        System.out.println(customer.getId());
        System.out.println(customer2.getId());
    }

    /**
     * 若传入的是一个游离对象,即传入的对象有OID
     * 1. 若在EntityManager缓存中没有该对象
     * 2. 若在数据库中也没有对象的记录
     * 3. JAP会创建一个新的对象,然后把游离对象的属性复制到新创建的对象中
     * 4. 对新创建的对象执行insert操作
     */
    @Test
    public void testMergeTwo() {
        Customer customer = new Customer();
        customer.setAge(18);
        customer.setBirth(new Date());
        customer.setEmail("dd@163.com");
        customer.setLastName("DD");

        customer.setId(100);

        Customer customer2 = entityManager.merge(customer);
        System.out.println(customer.getId());
        System.out.println(customer2.getId());
    }

    /**
     * 若传入的是一个游离对象,即传入的对象有OID
     * 1. 若在EntityManager缓存中没有该对象
     * 2. 若在数据库中也有对象的记录
     * 3. JAP会查询对象的记录,然后返回该记录对一对应的对象,再然后会把游离对象的属性复制到查询到的对象中
     * 4. 对查询到的对象执行update操作
     */
    @Test
    public void testMergeThree() {
        Customer customer = new Customer();
        customer.setAge(18);
        customer.setBirth(new Date());
        customer.setEmail("ee@163.com");
        customer.setLastName("EE");

        customer.setId(4);

        Customer customer2 = entityManager.merge(customer);
        System.out.println(customer.getId());
        System.out.println(customer2.getId());
    }

    /**
     * 若传入的是一个游离对象,即传入的对象有OID
     * 1. 若在EntityManager缓存中有对应的对象
     * 2. JPA会把游离对象的属性复制到查询到EntityManager缓存中的对象中
     * 3. EntityManager缓存中的对象执行UPDATE
     */
    @Test
    public void testMergeFour() {
        Customer customer = new Customer();
        customer.setAge(18);
        customer.setBirth(new Date());
        customer.setEmail("dd@163.com");
        customer.setLastName("DD");

        customer.setId(4);

        Customer customer2 = entityManager.find(Customer.class,4);
        entityManager.merge(customer);

    }

    /**
     * 同hibernate中Session中的flush
     */
    public void testFlush() {
        Customer customer = entityManager.find(Customer.class, 1);
        System.out.println(customer);

        customer.setLastName("BB");
        entityManager.flush();
    }

}

4.3 单向多对一

import com.atguigu.jpa.helloworld.Customer;
import com.atguigu.jpa.helloworld.Order;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.Date;

public class JpaTestThree {

    private EntityManagerFactory entityManagerFactory;
    private EntityManager entityManager;
    private EntityTransaction entityTransaction;

    @Before
    public void init() {
        //1. 创建EntityManagerFactory
        entityManagerFactory = Persistence.createEntityManagerFactory("NewPersistenceUnit");

        //2. 创建EntityManager
        entityManager = entityManagerFactory.createEntityManager();

        //3. 开启事务
        entityTransaction = entityManager.getTransaction();
        entityTransaction.begin();
    }

    @After
    public void destory() {
        entityTransaction.commit();
        entityManager.close();
        entityManagerFactory.close();
    }

    /**
     * 保存多对一时,建议先保存1的一端,后保存n的一端,这样不会多出额外的 UPDATE 语句
     */
    @Test
    public void testManyToOnePersist() {
        Customer customer = new Customer();
        customer.setAge(18);
        customer.setBirth(new Date());
        customer.setEmail("ff@163.com");
        customer.setLastName("FF");

        Order order1 = new Order();
        order1.setOrderName("O-FF-1");
        Order order2 = new Order();
        order2.setOrderName("O-FF-2");
        Order order3 = new Order();
        order3.setOrderName("O-FF-3");

        order1.setCustomer(customer);
        order2.setCustomer(customer);
        order3.setCustomer(customer);

        entityManager.persist(customer);
        entityManager.persist(order1);
        entityManager.persist(order2);
        entityManager.persist(order3);
    }

    /**
     * 默认情况下,使用左外连接的方式来获取n 的一端的对象和其关联的1的一端的对象
     * 可使用@ManyToOne的fetch属性来修改默认的关联属性的加载策略
     */
    @Test
    public void testManyToOneFind() {
        Order order = entityManager.find(Order.class, 1);
        System.out.println(order.getOrderName());

        System.out.println(order.getCustomer().getLastName());
    }

    /**
     * 不能直接删除1的一端,因为有外键约束。
     */
    @Test
    public void testManyToOneRemove() {
        Order order = entityManager.find(Order.class, 1);
        entityManager.remove(order);

        Customer customer = entityManager.find(Customer.class, 7);
        entityManager.remove(customer);
    }

    @Test
    public void testManyToOneUpdate() {
        Order order = entityManager.find(Order.class, 2);
        order.getCustomer().setLastName("FFF");
    }

}

4.4 单向一对多

package com.atguigu.jpa.helloworld;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

@Table(name = "JAP_CUSTOMERS")
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Customer {

    @Id
    //@GeneratedValue(strategy = GenerationType.AUTO)
    @TableGenerator(name = "ID_GENERATOR",
                    table = "jpa_id_generators",
                    pkColumnName = "PK_NAME",
                    pkColumnValue = "CUSTOMER_ID",
                    valueColumnName = "PK_VALUE",
                    allocationSize = 100)
    @GeneratedValue(strategy = GenerationType.TABLE,generator = "ID_GENERATOR")
    private Integer id;

    @Column(name = "LAST_NAME")
    private String lastName;

    private String email;

    private int age;

    @Temporal(TemporalType.TIMESTAMP)
    private Date createdTime;

    @Temporal(TemporalType.DATE)
    private Date birth;

    /**
     * 映射单向1-n的关联关系
     * 使用@OneToMany来映射1-n的关联关系
     * 使用@JoinColumn来映射外键列的名称
     * 可以使用@OneToMany的fetch属性来修改默认的加载策略
     */
    @JoinColumn(name = "CUSTOMER_ID")
    @OneToMany(fetch = FetchType.EAGER,cascade = {CascadeType.REMOVE})
    private Set<Order> orders=new HashSet<Order>();

    //工具方法,不需要映射为数据表的一列
    @Transient
    public String getInfo() {
        return "lastName:"+lastName+", email:"+email;
    }

    @Override
    public String toString() {
        return "Customer{" +
                "id=" + id +
                ", lastName='" + lastName + '\'' +
                ", email='" + email + '\'' +
                ", age=" + age +
                ", createdTime=" + createdTime +
                ", birth=" + birth +
                '}';
    }
}

package com.atguigu.jpa.helloworld;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Table(name = "JPA_ORDERS")
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Order {

    @Id
    @GeneratedValue
    private Integer id;

    @Column(name = "ORDER_NAME")
    private String orderName;

    /**
     * 映射单项n-1关联关系
     * 使用@ManyToOne来映射多对一的关联关系
     * 使用@JoinColumn来映射外键
     * 可使用@ManyToOne的fetch属性来修改默认的关联属性的加载策略
     */
    //@JoinColumn(name = "CUSTOMER_ID")
    //@ManyToOne(fetch = FetchType.LAZY)
    //private Customer customer;

}

import com.atguigu.jpa.helloworld.Customer;
import com.atguigu.jpa.helloworld.Order;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.Date;

public class JpaTestFour {

    private EntityManagerFactory entityManagerFactory;
    private EntityManager entityManager;
    private EntityTransaction entityTransaction;

    @Before
    public void init() {
        //1. 创建EntityManagerFactory
        entityManagerFactory = Persistence.createEntityManagerFactory("NewPersistenceUnit");

        //2. 创建EntityManager
        entityManager = entityManagerFactory.createEntityManager();

        //3. 开启事务
        entityTransaction = entityManager.getTransaction();
        entityTransaction.begin();
    }

    @After
    public void destory() {
        entityTransaction.commit();
        entityManager.close();
        entityManagerFactory.close();
    }

    /**
     * 单向1-n关联关系执行保存时,一定会多出UPDATE语句.
     * 因为n 的一端在插入时不会同时插入外键列。
     */
    @Test
    public void testOneToManyPersist() {
        Customer customer = new Customer();
        customer.setAge(18);
        customer.setBirth(new Date());
        customer.setEmail("zz@163.com");
        customer.setLastName("zz");

        Order order1 = new Order();
        order1.setOrderName("O-ZZ-1");
        Order order2 = new Order();
        order2.setOrderName("O-ZZ-2");

        customer.getOrders().add(order1);
        customer.getOrders().add(order2);

        entityManager.persist(customer);
        entityManager.persist(order1);
        entityManager.persist(order2);
    }

    /**
     * 默认对关联的多的一方使用懒加载的加载策略。
     * 可以使用@oneToMany的fetch属性来修改默认的载策略
     */
    @Test
    public void testOneToManyFind() {
        Customer customer = entityManager.find(Customer.class, 9);
        System.out.println(customer.getLastName());

        System.out.println(customer.getOrders().size());
    }

    /**
     * 默认情况下,若删除1的一端,则会把关联的n的一端的外键置空,然后进行删除
     * 可以通过@OneToMany的cascade属性来修改默认的到除策略
     */
    @Test
    public void testOneToManyRemove() {
        Customer customer = entityManager.find(Customer.class, 9);
        entityManager.remove(customer);
    }

    @Test
    public void testUpdate() {
        Customer customer = entityManager.find(Customer.class, 10);
        customer.getOrders().iterator().next().setOrderName("o-XX-10");
    }


}

4.4 双向一对多

package com.atguigu.jpa.helloworld;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

@Table(name = "JAP_CUSTOMERS")
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Customer {

    @Id
    //@GeneratedValue(strategy = GenerationType.AUTO)
    @TableGenerator(name = "ID_GENERATOR",
                    table = "jpa_id_generators",
                    pkColumnName = "PK_NAME",
                    pkColumnValue = "CUSTOMER_ID",
                    valueColumnName = "PK_VALUE",
                    allocationSize = 100)
    @GeneratedValue(strategy = GenerationType.TABLE,generator = "ID_GENERATOR")
    private Integer id;

    @Column(name = "LAST_NAME")
    private String lastName;

    private String email;

    private int age;

    @Temporal(TemporalType.TIMESTAMP)
    private Date createdTime;

    @Temporal(TemporalType.DATE)
    private Date birth;

    /**
     * 映射单向1-n的关联关系
     * 使用@OneToMany来映射1-n的关联关系
     * 使用@JoinColumn来映射外键列的名称
     * 可以使用@OneToMany的fetch属性来修改默认的加载策略
     * 注意:若在1的一端的@OneToNany中使用mapperBy 属性,则@OneToMany 端就不能再使用@JoinColumn 属性了
     */
    //@JoinColumn(name = "CUSTOMER_ID")
    @OneToMany(fetch = FetchType.EAGER,cascade = {CascadeType.REMOVE},mappedBy = "customer")
    private Set<Order> orders=new HashSet<Order>();

    //工具方法,不需要映射为数据表的一列
    @Transient
    public String getInfo() {
        return "lastName:"+lastName+", email:"+email;
    }

    @Override
    public String toString() {
        return "Customer{" +
                "id=" + id +
                ", lastName='" + lastName + '\'' +
                ", email='" + email + '\'' +
                ", age=" + age +
                ", createdTime=" + createdTime +
                ", birth=" + birth +
                '}';
    }
}

package com.atguigu.jpa.helloworld;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Table(name = "JPA_ORDERS")
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Order {

    @Id
    @GeneratedValue
    private Integer id;

    @Column(name = "ORDER_NAME")
    private String orderName;

    /**
     * 映射单项n-1关联关系
     * 使用@ManyToOne来映射多对一的关联关系
     * 使用@JoinColumn来映射外键
     * 可使用@ManyToOne的fetch属性来修改默认的关联属性的加载策略
     */
    @JoinColumn(name = "CUSTOMER_ID")
    @ManyToOne(fetch = FetchType.LAZY)
    private Customer customer;

}

import com.atguigu.jpa.helloworld.Customer;
import com.atguigu.jpa.helloworld.Order;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.Date;

public class JpaTestFour {

    private EntityManagerFactory entityManagerFactory;
    private EntityManager entityManager;
    private EntityTransaction entityTransaction;

    @Before
    public void init() {
        //1. 创建EntityManagerFactory
        entityManagerFactory = Persistence.createEntityManagerFactory("NewPersistenceUnit");

        //2. 创建EntityManager
        entityManager = entityManagerFactory.createEntityManager();

        //3. 开启事务
        entityTransaction = entityManager.getTransaction();
        entityTransaction.begin();
    }

    @After
    public void destory() {
        entityTransaction.commit();
        entityManager.close();
        entityManagerFactory.close();
    }

    /**
     * 若是双向1-n的关联关系,执行保存时
     * 若先保存n 的一端,再保存1的一端,默认情况下,会多出n条 UPDATE语句。
     * 若先保存1的一端,则会多出n条UPDATE 语句
     * 在进行双向1-n 关联关系时,建议使用n 的一方来维护关联关系,而1的一方不维护关联系这样会有效的减少SOL语句.
     * 注意:若在1的一端的@OneToNany中使用mapperBy 属性,则@OneToMany 端就不能再使用@JoinColumn 属性了
     */
    @Test
    public void testOneToManyPersist() {
        Customer customer = new Customer();
        customer.setAge(18);
        customer.setBirth(new Date());
        customer.setEmail("zz@163.com");
        customer.setLastName("zz");

        Order order1 = new Order();
        order1.setOrderName("O-ZZ-1");
        Order order2 = new Order();
        order2.setOrderName("O-ZZ-2");

        customer.getOrders().add(order1);
        customer.getOrders().add(order2);

        order1.setCustomer(customer);
        order2.setCustomer(customer);

        entityManager.persist(customer);
        entityManager.persist(order1);
        entityManager.persist(order2);
    }
}

4.5 双向一对一

package com.atguigu.jpa.helloworld;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Table(name = "JAP_DEPARTMENTS")
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Department {

    @Id
    @GeneratedValue
    private Integer id;

    @Column(name = "DEPT_NAME")
    private String deptName;

    /**
     * 使用@OneToOne来映射1-1关联关系。
     * 若需要在当前数据表中添加主健则需要使用@JoinColumn 来进行映射。
     * 注意,1-1关联关系,所以需要添加unique=true
     */
    @JoinColumn(name = "MGR_ID",unique = true)
    @OneToOne(fetch = FetchType.LAZY)
    private Manager mgr;

}

package com.atguigu.jpa.helloworld;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Table(name = "JAP_MANAGERS")
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Manager {


    @Id
    @GeneratedValue
    private Integer id;

    @Column(name = "MGR_NAME")
    private String mgrName;

    /**
     * 对于不维护关联关系,没有外键的一方,使用@OneTo0ne来进行映射,建议设置mappedBy
     */
    @OneToOne(mappedBy = "mgr")
    private Department dept;
}

import com.atguigu.jpa.helloworld.Department;
import com.atguigu.jpa.helloworld.Manager;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

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

public class JpaTestFour {

    private EntityManagerFactory entityManagerFactory;
    private EntityManager entityManager;
    private EntityTransaction entityTransaction;

    @Before
    public void init() {
        //1. 创建EntityManagerFactory
        entityManagerFactory = Persistence.createEntityManagerFactory("NewPersistenceUnit");

        //2. 创建EntityManager
        entityManager = entityManagerFactory.createEntityManager();

        //3. 开启事务
        entityTransaction = entityManager.getTransaction();
        entityTransaction.begin();
    }

    @After
    public void destory() {
        entityTransaction.commit();
        entityManager.close();
        entityManagerFactory.close();
    }

    /**
     * 双向1-1的关联关系,建议先保存不维护关联关系的一方,
     * 即没有外键的一方,这样不会多出UPDATE语句
     */
    @Test
    public void testOneToOnePersistence() {
        Manager mgr = new Manager();
        mgr.setMgrName("M-BB");

        Department dept = new Department();
        dept.setDeptName("D-BB");

        mgr.setDept(dept);
        dept.setMgr(mgr);

        entityManager.persist(dept);
        entityManager.persist(mgr);
    }

    /**
     * 1.默认情况下,若获取维护关联关系的一方,则会通过左外连接获取其关联的对象。
     * 但可以通过@OntTo0ne 的fetch属性来修改加载策略。
     */
    @Test
    public void testOneToOneFind() {
        Department dept = entityManager.find(Department.class, 1);
        System.out.println(dept.getDeptName());
        System.out.println(dept.getMgr().getClass().getName());
    }
}

4.6 双向多对多

package com.atguigu.jpa.helloworld;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import java.util.HashSet;
import java.util.Set;

@Table(name = "JPA_ITEMS")
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Item {

    @Id
    @GeneratedValue
    private Integer id;

    @Column(name = "ITEM_NAME")
    private String itemName;

    /**
     * 使用@ManyToMany 注解来映射多对多关联关系使用
     * @JoinTable 来映射中间表
     * 1. name指向中间表的名字
     * 2.joincolumns映射当前类所在的表在中间表中的外键
     * 2.1 name指定外键列的列名
     * 2.2 referencedColumnName指定外键列关联当前表的哪一列
     * 3. inverseJoincolumns映射关联的类所在中间表的外键
     */
    @JoinTable(name = "ITEM_CATEGORY",
               joinColumns = {@JoinColumn(name = "ITEM_ID",referencedColumnName = "ID")},
               inverseJoinColumns = {@JoinColumn(name = "CATEGORY_ID",referencedColumnName = "ID")})
    @ManyToMany
    private Set<Category> categories=new HashSet<Category>();

}

package com.atguigu.jpa.helloworld;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import java.util.HashSet;
import java.util.Set;

@Table(name = "JPA_CATEGORIES")
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Category {

    @Id
    @GeneratedValue
    private Integer id;

    @Column(name = "GENTORY_NAME")
    private String categoryName;

    @ManyToMany(mappedBy = "categories")
    private Set<Item> items=new HashSet<Item>();

}

import com.atguigu.jpa.helloworld.Category;
import com.atguigu.jpa.helloworld.Item;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

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

public class JpaTestFour {

    private EntityManagerFactory entityManagerFactory;
    private EntityManager entityManager;
    private EntityTransaction entityTransaction;

    @Before
    public void init() {
        //1. 创建EntityManagerFactory
        entityManagerFactory = Persistence.createEntityManagerFactory("NewPersistenceUnit");

        //2. 创建EntityManager
        entityManager = entityManagerFactory.createEntityManager();

        //3. 开启事务
        entityTransaction = entityManager.getTransaction();
        entityTransaction.begin();
    }

    @After
    public void destory() {
        entityTransaction.commit();
        entityManager.close();
        entityManagerFactory.close();
    }

    /**
     * 多对所的保存
     */
    @Test
    public void testManyToManyPersist(){
        Item i1 = new Item();
        i1.setItemName("i-1");

        Item i2 = new Item();
        i2.setItemName("i-2");

        Category c1 = new Category();
        c1.setCategoryName("C-1");

        Category c2 = new Category();
        c2.setCategoryName("C-2");

        //设置关联关系
        i1.getCategories().add(c1);
        i1.getCategories().add(c2);

        i2.getCategories().add(c1);
        i2.getCategories().add(c2);

        c1.getItems().add(i1);
        c1.getItems().add(i2);

        c2.getItems().add(i1);
        c2.getItems().add(i2);

        //执行保存
        entityManager.persist(i1);
        entityManager.persist(i2);
        entityManager.persist(c1);
        entityManager.persist(c2);
    }

    /**
     * 对于关联的集合对象, 默认使用懒加载的策略.
     * 使用维护关联关系的一方获取, 还是使用不维护关联关系的一方获取, SQL 语句相同.
     */
    @Test
    public void testManyToManyFind(){
		//Item item = entityManager.find(Item.class, 5);
		//System.out.println(item.getItemName());
		//
		//System.out.println(item.getCategories().size());

        Category category = entityManager.find(Category.class, 3);
        System.out.println(category.getCategoryName());
        System.out.println(category.getItems().size());
    }
}

第五章 IDEA建立JPA工程过程

![在这里插入图片描述]( https://img-blog.csdnimg.cn/3d10dae299374753b18fd0d1c20c5542.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/2ecb14193f994f81adc0eb758ef03517.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/fee8382111ed4e6292fa491959279520.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/24a8b736a51342ce9668e4fa1eaab2ba.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/7d6f96d0f1024e2b941f41aa0b3e3c95.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_18,color_FFFFFF,t_70,g_se,x_16)
导入依赖

    <dependencies>

        <!--hibernate包-->
        <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>4.2.4.Final</version>
        </dependency>

        <!--mysql包-->
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

        <!--lombok包-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.4</version>
            <scope>provided</scope>
        </dependency>

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

        <!--c3p0包-->
        <!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.2</version>
        </dependency>

        <!--hibernate-c3p0包-->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-c3p0</artifactId>
            <version>4.2.5.Final</version>
        </dependency>

        <!--  jpa-hibernate包-->
        <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-entitymanager -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>4.2.4.Final</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/net.sf.ehcache/ehcache -->
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
            <version>2.4.3</version>
            <type>pom</type>
        </dependency>

        <!-- hibernate-ehcache -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-ehcache</artifactId>
            <version>4.2.4.Final</version>
        </dependency>
    </dependencies>

第六章 二级缓存代码示例

![在这里插入图片描述]( https://img-blog.csdnimg.cn/0e9b62106a5843ee8ceb6e2c12f2ec69.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_15,color_FFFFFF,t_70,g_se,x_16)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>groupId</groupId>
    <artifactId>jpa-1</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>

        <!--hibernate包-->
        <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>4.2.4.Final</version>
        </dependency>

        <!--mysql包-->
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

        <!--lombok包-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.4</version>
            <scope>provided</scope>
        </dependency>

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

        <!--c3p0包-->
        <!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.2</version>
        </dependency>

        <!--hibernate-c3p0包-->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-c3p0</artifactId>
            <version>4.2.5.Final</version>
        </dependency>

        <!--  jpa-hibernate包-->
        <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-entitymanager -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>4.2.4.Final</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/net.sf.ehcache/ehcache -->
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
            <version>2.4.3</version>
            <type>pom</type>
        </dependency>

        <!-- hibernate-ehcache -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-ehcache</artifactId>
            <version>4.2.4.Final</version>
        </dependency>
    </dependencies>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">

    <persistence-unit name="NewPersistenceUnit">

        <!--
          配置使用什么ORM产品来作为JPA的实现
          1.实际上配置的是javax.persistence.spi.PersistenceProvider接口的实现类
          2.若JPA项目中只有一个JPA的实现产品,则也可以不配置该节点。
        -->
        <provider>org.hibernate.ejb.HibernatePersistence</provider>

        <!--添加持久化类-->
        <class>com.atguigu.jpa.helloworld.Customer</class>
        <class>com.atguigu.jpa.helloworld.Order</class>
        <class>com.atguigu.jpa.helloworld.Department</class>
        <class>com.atguigu.jpa.helloworld.Manager</class>

        <!--配置二级缓存的策略
            ALL:所有的实体类都被缓存
            NONE:所有的实体类都不被缓存.
            ENABLE_SELECTIVE:标识 @Cacheable(true) 注解的实体类将被缓存
            DISABLE_SELECTIVE:缓存除标识 @Cacheable(false) 以外的所有实体类
            UNSPECIFIED:默认值,JPA 产品默认值将被使用
        -->
        <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>

        <properties>
            <!--连接数据库的基本信息-->
            <property name="hibernate.connection.url" value="jdbc:mysql://172.16.19.104:3306/jpa1"/>
            <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
            <property name="hibernate.connection.username" value="springcloud"/>
            <property name="hibernate.connection.password" value="springcloud"/>

            <!-- 配置JPA实现产品的基本属性,配置hibernate的基本属性-->
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.hbm2ddl.auto" value="update"/>

            <!-- 启用二级缓存 -->
            <property name="cache.use_second_level_cache" value="true"/>

            <!-- 配置使用的二级缓存的产品 -->
            <property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory" />

            <!-- 配置启用查询缓存 -->
            <property name="cache.use_query_cache" value="true" />
        </properties>
    </persistence-unit>
</persistence>

<ehcache>

    <!-- Sets the path to the directory where cache .data files are created.

         If the path is a Java System Property it is replaced by
         its value in the running VM.

         The following properties are translated:
         user.home - User's home directory
         user.dir - User's current working directory
         java.io.tmpdir - Default temp file path -->
    <!--  
    	指定一个目录:当 EHCache 把数据写到硬盘上时, 将把数据写到这个目录下.
    -->     
    <diskStore path="d:\\tempDirectory"/>


    <!--Default Cache configuration. These will applied to caches programmatically created through
        the CacheManager.

        The following attributes are required for defaultCache:

        maxInMemory       - Sets the maximum number of objects that will be created in memory
        eternal           - Sets whether elements are eternal. If eternal,  timeouts are ignored and the element
                            is never expired.
        timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used
                            if the element is not eternal. Idle time is now - last accessed time
        timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used
                            if the element is not eternal. TTL is now - creation time
        overflowToDisk    - Sets whether elements can overflow to disk when the in-memory cache
                            has reached the maxInMemory limit.

        -->
    <!--  
    	设置缓存的默认数据过期策略 
    -->    
    <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true"
        />

   	<!--  
   		设定具体的命名缓存的数据过期策略。每个命名缓存代表一个缓存区域
   		缓存区域(region):一个具有名称的缓存块,可以给每一个缓存块设置不同的缓存策略。
   		如果没有设置任何的缓存区域,则所有被缓存的对象,都将使用默认的缓存策略。即:<defaultCache.../>
   		Hibernate 在不同的缓存区域保存不同的类/集合。
			对于类而言,区域的名称是类名。如:com.atguigu.domain.Customer
			对于集合而言,区域的名称是类名加属性名。如com.atguigu.domain.Customer.orders
   	-->
   	<!--  
   		name: 设置缓存的名字,它的取值为类的全限定名或类的集合的名字 
		maxElementsInMemory: 设置基于内存的缓存中可存放的对象最大数目 
		
		eternal: 设置对象是否为永久的, true表示永不过期,
		此时将忽略timeToIdleSeconds 和 timeToLiveSeconds属性; 默认值是false 
		timeToIdleSeconds:设置对象空闲最长时间,以秒为单位, 超过这个时间,对象过期。
		当对象过期时,EHCache会把它从缓存中清除。如果此值为0,表示对象可以无限期地处于空闲状态。 
		timeToLiveSeconds:设置对象生存最长时间,超过这个时间,对象过期。
		如果此值为0,表示对象可以无限期地存在于缓存中. 该属性值必须大于或等于 timeToIdleSeconds 属性值 
		
		overflowToDisk:设置基于内存的缓存中的对象数目达到上限后,是否把溢出的对象写到基于硬盘的缓存中 
   	-->
    <cache name="com.atguigu.hibernate.entities.Employee"
        maxElementsInMemory="1"
        eternal="false"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600"
        overflowToDisk="true"
        />

    <cache name="com.atguigu.hibernate.entities.Department.emps"
        maxElementsInMemory="1000"
        eternal="true"
        timeToIdleSeconds="0"
        timeToLiveSeconds="0"
        overflowToDisk="false"
        />

</ehcache>

package com.atguigu.jpa.helloworld;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import java.util.HashSet;
import java.util.Set;

@Table(name = "JPA_CATEGORIES")
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Category {

    @Id
    @GeneratedValue
    private Integer id;

    @Column(name = "GENTORY_NAME")
    private String categoryName;

    @ManyToMany(mappedBy = "categories")
    private Set<Item> items=new HashSet<Item>();

}

package com.atguigu.jpa.helloworld;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import java.util.HashSet;
import java.util.Set;

@Table(name = "JPA_ITEMS")
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Item {

    @Id
    @GeneratedValue
    private Integer id;

    @Column(name = "ITEM_NAME")
    private String itemName;

    /**
     * 使用@ManyToMany 注解来映射多对多关联关系使用
     * @JoinTable 来映射中间表
     * 1. name指向中间表的名字
     * 2.joincolumns映射当前类所在的表在中间表中的外键
     * 2.1 name指定外键列的列名
     * 2.2 referencedColumnName指定外键列关联当前表的哪一列
     * 3. inverseJoincolumns映射关联的类所在中间表的外键
     */
    @JoinTable(name = "ITEM_CATEGORY",
               joinColumns = {@JoinColumn(name = "ITEM_ID",referencedColumnName = "ID")},
               inverseJoinColumns = {@JoinColumn(name = "CATEGORY_ID",referencedColumnName = "ID")})
    @ManyToMany
    private Set<Category> categories=new HashSet<Category>();

}

package com.atguigu.jpa.helloworld;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Cacheable;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

@Cacheable(true)
@Table(name = "JAP_CUSTOMERS")
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Customer {

    @Id
    //@GeneratedValue(strategy = GenerationType.AUTO)
    @TableGenerator(name = "ID_GENERATOR",
                    table = "jpa_id_generators",
                    pkColumnName = "PK_NAME",
                    pkColumnValue = "CUSTOMER_ID",
                    valueColumnName = "PK_VALUE",
                    allocationSize = 100)
    @GeneratedValue(strategy = GenerationType.TABLE,generator = "ID_GENERATOR")
    private Integer id;

    @Column(name = "LAST_NAME")
    private String lastName;

    private String email;

    private int age;

    @Temporal(TemporalType.TIMESTAMP)
    private Date createdTime;

    @Temporal(TemporalType.DATE)
    private Date birth;

    /**
     * 映射单向1-n的关联关系
     * 使用@OneToMany来映射1-n的关联关系
     * 使用@JoinColumn来映射外键列的名称
     * 可以使用@OneToMany的fetch属性来修改默认的加载策略
     * 注意:若在1的一端的@OneToNany中使用mapperBy 属性,则@OneToMany 端就不能再使用@JoinColumn 属性了
     */
    //@JoinColumn(name = "CUSTOMER_ID")
    @OneToMany(fetch = FetchType.LAZY,cascade = {CascadeType.REMOVE},mappedBy = "customer")
    private Set<Order> orders=new HashSet<Order>();

    //工具方法,不需要映射为数据表的一列
    @Transient
    public String getInfo() {
        return "lastName:"+lastName+", email:"+email;
    }

    @Override
    public String toString() {
        return "Customer{" +
                "id=" + id +
                ", lastName='" + lastName + '\'' +
                ", email='" + email + '\'' +
                ", age=" + age +
                ", createdTime=" + createdTime +
                ", birth=" + birth +
                '}';
    }
}

package com.atguigu.jpa.helloworld;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Table(name = "JAP_DEPARTMENTS")
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Department {

    @Id
    @GeneratedValue
    private Integer id;

    @Column(name = "DEPT_NAME")
    private String deptName;

    /**
     * 使用@OneToOne来映射1-1关联关系。
     * 若需要在当前数据表中添加主健则需要使用@JoinColumn 来进行映射。
     * 注意,1-1关联关系,所以需要添加unique=true
     */
    @JoinColumn(name = "MGR_ID",unique = true)
    @OneToOne(fetch = FetchType.LAZY)
    private Manager mgr;

}

package com.atguigu.jpa.helloworld;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Table(name = "JAP_MANAGERS")
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Manager {


    @Id
    @GeneratedValue
    private Integer id;

    @Column(name = "MGR_NAME")
    private String mgrName;

    /**
     * 对于不维护关联关系,没有外键的一方,使用@OneTo0ne来进行映射,建议设置mappedBy
     */
    @OneToOne(mappedBy = "mgr")
    private Department dept;
}

package com.atguigu.jpa.helloworld;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Table(name = "JPA_ORDERS")
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Order {

    @Id
    @GeneratedValue
    private Integer id;

    @Column(name = "ORDER_NAME")
    private String orderName;

    /**
     * 映射单项n-1关联关系
     * 使用@ManyToOne来映射多对一的关联关系
     * 使用@JoinColumn来映射外键
     * 可使用@ManyToOne的fetch属性来修改默认的关联属性的加载策略
     */
    @JoinColumn(name = "CUSTOMER_ID")
    @ManyToOne(fetch = FetchType.LAZY)
    private Customer customer;

}

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

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

public class JpaTestFour {

    private EntityManagerFactory entityManagerFactory;
    private EntityManager entityManager;
    private EntityTransaction entityTransaction;

    @Before
    public void init() {
        //1. 创建EntityManagerFactory
        entityManagerFactory = Persistence.createEntityManagerFactory("NewPersistenceUnit");

        //2. 创建EntityManager
        entityManager = entityManagerFactory.createEntityManager();

        //3. 开启事务
        entityTransaction = entityManager.getTransaction();
        entityTransaction.begin();
    }

    @After
    public void destory() {
        entityTransaction.commit();
        entityManager.close();
        entityManagerFactory.close();
    }

    @Test
    public void test() {
        Customer customer = entityManager.find(Customer.class, 1);
        System.out.println(customer);

        entityTransaction.commit();
        entityManager.close();

        entityManager = entityManagerFactory.createEntityManager();
        entityTransaction = entityManager.getTransaction();
        entityTransaction.begin();

        Customer customer1 = entityManager.find(Customer.class, 1);
        System.out.println(customer1);

    }


}

第七章 JPQL

7.1 介绍

![在这里插入图片描述]( https://img-blog.csdnimg.cn/d93bd2e2e1bf45b79632911703d750d6.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/f54e42ce481347e5baede6abbde88d59.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/e12aa2c29d764d478bd10fc4a4ab76d9.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/574cbcf729d84014863b4a74917d2e29.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/1476ed52d7b543b28e1758b593ddef7c.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

7.2 select语句

select-from

![在这里插入图片描述]( https://img-blog.csdnimg.cn/74c46620bd154cf59da5e753d17398dd.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

查询所有实体

![在这里插入图片描述]( https://img-blog.csdnimg.cn/c4badb063b87456f8a5a525f5c2724a8.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/8d64d59db3774ccca4d49a242319e840.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

where子句

![在这里插入图片描述]( https://img-blog.csdnimg.cn/b7c3419fd2174138a78a6fdbb62c221b.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/92ba07d7714949e4bc46cb12943bcfdf.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/f882379d8b0e47f8998ce07790f0936d.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/ffefc0f224344738a06aa295df3a75e6.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

查询部分属性

![在这里插入图片描述]( https://img-blog.csdnimg.cn/8543a7fd58c94439a8e6326c0b545f77.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

使用Hibernate的查询缓存

在这里插入图片描述

oraer by子句

![在这里插入图片描述]( https://img-blog.csdnimg.cn/788ef64b944b42bfb8b592cb1139054e.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

group by子句与聚合查询

![在这里插入图片描述]( https://img-blog.csdnimg.cn/4a186d766de543629d59cf21d253d7b2.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

having子句

![在这里插入图片描述]( https://img-blog.csdnimg.cn/306504376e9a4155a5a73f2d59e85d21.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

关联查询

![在这里插入图片描述]( https://img-blog.csdnimg.cn/a41e71b54a17400e96d17a73649cefec.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/02f8234cb8fe40888710f4fa2ebfd919.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

子查询

![在这里插入图片描述]( https://img-blog.csdnimg.cn/01c9ae48ecfe46cbadd82e30447a996c.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

JPQL函数

![在这里插入图片描述]( https://img-blog.csdnimg.cn/39edc07491974dfe96e63e64d3016618.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/30cea511c40f417486a545595073e100.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

update语句

![在这里插入图片描述]( https://img-blog.csdnimg.cn/950e1c76ae2147a2977b5a3fa674f6de.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

delete语句

![在这里插入图片描述]( https://img-blog.csdnimg.cn/45703bce4494449dbba44b90e631ae60.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)

第七章 代码总结

![在这里插入图片描述]( https://img-blog.csdnimg.cn/35823464a0ea452faf4eb0389b25302a.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_12,color_FFFFFF,t_70,g_se,x_16)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>groupId</groupId>
    <artifactId>jpa-2</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>

        <!--hibernate包-->
        <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>4.2.4.Final</version>
        </dependency>

        <!--mysql包-->
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

        <!--lombok包-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.4</version>
            <scope>provided</scope>
        </dependency>

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

        <!--c3p0包-->
        <!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.2</version>
        </dependency>

        <!--hibernate-c3p0包-->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-c3p0</artifactId>
            <version>4.2.5.Final</version>
        </dependency>

        <!--  jpa-hibernate包-->
        <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-entitymanager -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>4.2.4.Final</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/net.sf.ehcache/ehcache -->
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
            <version>2.4.3</version>
            <type>pom</type>
        </dependency>

        <!-- hibernate-ehcache -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-ehcache</artifactId>
            <version>4.2.4.Final</version>
        </dependency>
    </dependencies>
    
</project>
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">

    <persistence-unit name="NewPersistenceUnit">

        <!--
          配置使用什么ORM产品来作为JPA的实现
          1.实际上配置的是javax.persistence.spi.PersistenceProvider接口的实现类
          2.若JPA项目中只有一个JPA的实现产品,则也可以不配置该节点。
        -->
        <provider>org.hibernate.ejb.HibernatePersistence</provider>

        <!--添加持久化类-->
        <class>entity.Customer</class>
        <class>entity.Order</class>

        <properties>
            <!--连接数据库的基本信息-->
            <property name="hibernate.connection.url" value="jdbc:mysql://172.16.19.104:3306/jpa1"/>
            <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
            <property name="hibernate.connection.username" value="springcloud"/>
            <property name="hibernate.connection.password" value="springcloud"/>

            <!-- 配置JPA实现产品的基本属性,配置hibernate的基本属性-->
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.hbm2ddl.auto" value="update"/>

        </properties>

    </persistence-unit>



</persistence>

package entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

@NamedQuery(name="testNamedQuery",query = "select c from Customer c where c.id=?")
@Table(name = "JAP_CUSTOMERS")
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Customer {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @Column(name = "LAST_NAME")
    private String lastName;

    private String email;

    private int age;

    @Temporal(TemporalType.TIMESTAMP)
    private Date createdTime;

    @Temporal(TemporalType.DATE)
    private Date birth;

    /**
     * 映射单向1-n的关联关系
     * 使用@OneToMany来映射1-n的关联关系
     * 使用@JoinColumn来映射外键列的名称
     * 可以使用@OneToMany的fetch属性来修改默认的加载策略
     * 注意:若在1的一端的@OneToNany中使用mapperBy 属性,则@OneToMany 端就不能再使用@JoinColumn 属性了
     */
    //@JoinColumn(name = "CUSTOMER_ID")
    @OneToMany(fetch = FetchType.LAZY,cascade = {CascadeType.REMOVE},mappedBy = "customer")
    private Set<Order> orders=new HashSet<Order>();

    //工具方法,不需要映射为数据表的一列
    @Transient
    public String getInfo() {
        return "lastName:"+lastName+", email:"+email;
    }

    public Customer(String lastName, int age) {
        this.lastName = lastName;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Customer{" +
                "id=" + id +
                ", lastName='" + lastName + '\'' +
                ", email='" + email + '\'' +
                ", age=" + age +
                ", createdTime=" + createdTime +
                ", birth=" + birth +
                '}';
    }

}

package entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Table(name = "JPA_ORDERS")
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Order {

    @Id
    @GeneratedValue
    private Integer id;

    @Column(name = "ORDER_NAME")
    private String orderName;

    /**
     * 映射单项n-1关联关系
     * 使用@ManyToOne来映射多对一的关联关系
     * 使用@JoinColumn来映射外键
     * 可使用@ManyToOne的fetch属性来修改默认的关联属性的加载策略
     */
    @JoinColumn(name = "CUSTOMER_ID")
    @ManyToOne(fetch = FetchType.LAZY)
    private Customer customer;

}

import entity.Customer;
import entity.Order;
import org.hibernate.ejb.QueryHints;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

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

public class JpqlTest {

    private EntityManagerFactory entityManagerFactory;
    private EntityManager entityManager;
    private EntityTransaction entityTransaction;

    @Before
    public void init() {
        //1. 创建EntityManagerFactory
        entityManagerFactory = Persistence.createEntityManagerFactory("NewPersistenceUnit");

        //2. 创建EntityManager
        entityManager = entityManagerFactory.createEntityManager();

        //3. 开启事务
        entityTransaction = entityManager.getTransaction();
        entityTransaction.begin();
    }

    @After
    public void destory() {
        entityTransaction.commit();
        entityManager.close();
        entityManagerFactory.close();
    }

    /**
     * JPQL的HelloWorld
     */
    @Test
    public void testHelloJPQL() {
        String jpql="FROM Customer C WHERE C.age > ?";
        Query query = entityManager.createQuery(jpql);

        //占位符的索引是从1开始
        query.setParameter(1,1);
        List<Customer> customerList = query.getResultList();
        System.out.println(customerList.size());

    }

    /**
     * JPQL设置属性
     */
    @Test
    public void testPartlyProperties() {

        //默认情况下,若只查询部分属性,则将返回0bject[]类型的结果。或者0bject[]类型的List.
        String jpal="select c.lastName,c.age from Customer c WHERE  c.id>?";
        List resultList = entityManager.createQuery(jpal).setParameter(1, 1).getResultList();

        System.out.println(resultList);
    }

    /**
     * JPQL属性返回对象
     */
    @Test
    public void testPartlyPropertiesTwo() {

        //默认情况下,若只查询部分属性,则将返回0bject[]类型的结果。或者0bject[]类型的List.
        String jpal="select new Customer (c.lastName,c.age)from Customer c WHERE  c.id>?";
        List resultList = entityManager.createQuery(jpal).setParameter(1, 1).getResultList();

        System.out.println(resultList);
    }

    /**
     * createNamedQuery适用于在实体类前使用@NamedQuery 标记的查询语句
     */
    @Test
    public void testNamedQuery() {
        Query query = entityManager.createNamedQuery("testNamedQuery").setParameter(1, 3);
        Customer customer =(Customer) query.getSingleResult();
        System.out.println(customer);
    }

    /**
     * createNativeQuery 适用于本地SQL
     */
    @Test
    public void testNativeQuery() {
        String sql="SELECT age from jap_customers where id =?";
        Query query = entityManager.createNativeQuery(sql).setParameter(1, 3);
        Object result = query.getSingleResult();
        System.out.println(result);
    }

    /**
     * JPQL查询二级缓存
     * 如果没有二级缓存,两个query.getResultList()会发送两个select语句
     */
    @Test
    public void testQueryCache() {
        String jpql ="FROM Customer c WHERE c.age >?";
        Query query = entityManager.createQuery(jpql) .setHint(QueryHints.HINT_CACHEABLE,true);

        //占位符的索引是从1开始
        query.setParameter(1,1);
        List<Customer> customers = query.getResultList();
        System.out.println(customers.size());

        query = entityManager.createQuery(jpql).setHint(QueryHints.HINT_CACHEABLE, true);

        //占位符的索引是从1开始
        query.setParameter(1,1);
        customers = query.getResultList();
        System.out.println(customers.size());

    }

    /**
     * JPQL的order by
     */
    @Test
    public void testOrderBy() {
        String jpql="FROM Customer c where c.age>? ORDER BY c.age DESC";
        Query query = entityManager.createQuery(jpql);

        query.setParameter(1,1);
        List<Customer> customerList = query.getResultList();
        System.out.println(customerList.size());
    }

    /**
     * 查询order数量大于2的那些customer
     */
    @Test
    public void testGroupBy() {
        String jpql="select o.customer from Order o group by o.customer having count(o.id)>=2";
        List<Customer> resultList = entityManager.createQuery(jpql).getResultList();

        System.out.println(resultList);
    }

    /**
     * JPQL的关联查询同HQL的关联查询.
     */
    @Test
    public void testLeftOuterJoinFetch() {
        String jpql="FROM Customer c LEFT OUTER JOIN FETCH c.orders where c.id=?";
        Customer customer = (Customer)entityManager.createQuery(jpql).setParameter(1, 12).getSingleResult();
        System.out.println(customer.getLastName());

    }

    /**
     * JPQL的子查询
     */
    @Test
    public void testSubQuery() {
        String jpql="select o from Order o where o.customer=(select c from Customer c where c.lastName=?)";
        Query query = entityManager.createQuery(jpql).setParameter(1, "YY");
        List<Order> orderList = query.getResultList();
        System.out.println(orderList.size());
    }

    /**
     * 使用jpql内建的函数
     */
    @Test
    public void testJpqlFunction() {
        String jpql="select lower(c.email) from Customer c";
        List<String> emailList = entityManager.createQuery(jpql).getResultList();
        System.out.println(emailList);
    }

    /**
     * 可以使用PQL完成 UPDATE 和DELETE 操作
     */
    @Test
    public void testExecuteUpdate() {
        String jpql="update Customer c set c.lastName=? where c.id=?";
        Query query = entityManager.createQuery(jpql).setParameter(1, "YYY").setParameter(2, 12);
        query.executeUpdate();
    }


}

第八章 整合Spring

![在这里插入图片描述]( https://img-blog.csdnimg.cn/f9df1761720c4d44af3595cbe3a0ee5c.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_20,color_FFFFFF,t_70,g_se,x_16)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/d8fe92697b944e4d877eafaee74c15e2.png?x-oss-process=image/watermark ,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p2O6LS65qKW5qKW,size_11,color_FFFFFF,t_70,g_se,x_16)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>jpa-2</artifactId>
    <version>1.0-SNAPSHOT</version>

    <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>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.4</version>
            <scope>provided</scope>
        </dependency>

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

        <!--spring start-->
        <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 start-->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <!--hibernate-jap-->
        <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-->
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>${c3p0.version}</version>
        </dependency>

        <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>


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

        <!--spring-data-jpa-->
        <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>
    </dependencies>

</project>
jdbc.user=root
jdbc.password=1230
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql:///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:context="http://www.springframework.org/schema/context"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">

	<!-- 配置自动扫描的包 -->
	<context:component-scan base-package="com.atguigu.jpa"></context:component-scan>

	<!-- 配置 C3P0 数据源 -->
	<context:property-placeholder location="classpath:db.properties"/>

	<bean id="dataSource"
		class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="user" value="${jdbc.user}"></property>
		<property name="password" value="${jdbc.password}"></property>
		<property name="driverClass" value="${jdbc.driverClass}"></property>
		<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>	
		
		<!-- 配置其他属性 -->
	</bean>
	
	<!-- 配置 EntityManagerFactory -->
	<bean id="entityManagerFactory"
		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
		<property name="dataSource" ref="dataSource"></property>
		<!-- 配置 JPA 提供商的适配器. 可以通过内部 bean 的方式来配置 -->
		<property name="jpaVendorAdapter">
			<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"></bean>
		</property>	
		<!-- 配置实体类所在的包 -->
		<property name="packagesToScan" value="com.atguigu.jpa.spring.entities"></property>
		<!-- 配置 JPA 的基本属性. 例如 JPA 实现产品的属性 -->
		<property name="jpaProperties">
			<props>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.format_sql">true</prop>
				<prop key="hibernate.hbm2ddl.auto">update</prop>
			</props>
		</property>
	</bean>
	
	<!-- 配置 JPA 使用的事务管理器 -->
	<bean id="transactionManager"
		class="org.springframework.orm.jpa.JpaTransactionManager">
		<property name="entityManagerFactory" ref="entityManagerFactory"></property>	
	</bean>
	
	<!-- 配置支持基于注解是事务配置 -->
	<tx:annotation-driven transaction-manager="transactionManager"/>

</beans>

package com.atguigu.jpa.spring.entities;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Table(name="JPA_PERSONS")
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person {

    @Id
    @GeneratedValue
    private Integer id;

    @Column(name="LAST_NAME")
    private String lastName;

    private String email;

    private int age;

}

package com.atguigu.jpa.dao;

import com.atguigu.jpa.spring.entities.Person;
import org.springframework.stereotype.Repository;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Repository
public class PersonDao {

    /**
     * 如何获取到和当前事务关联的 EntityManager 对象呢 ?
     * 通过 @PersistenceContext 注解来标记成员变量!
     */
    @PersistenceContext
    private EntityManager entityManager;


    public void save(Person p1) {
        entityManager.persist(p1);
    }
}

package com.atguigu.jpa.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.atguigu.jpa.dao.PersonDao;
import com.atguigu.jpa.spring.entities.Person;

@Service
public class PersonService {
	
	@Autowired
	private PersonDao personDao;
	
	@Transactional
	public void savePersons(Person p1, Person p2){
		personDao.save(p1);
		
		int i = 10 / 0;
		
		personDao.save(p2);
	}
	
}

import com.atguigu.jpa.service.PersonService;
import com.atguigu.jpa.spring.entities.Person;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import javax.sql.DataSource;
import java.sql.SQLException;

public class JPATest {
	
	private ApplicationContext ctx = null;
	private PersonService personService = null;
	
	{
		ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
		personService = ctx.getBean(PersonService.class);
	}
	
	@Test
	public void testPersonService(){
		Person p1 = new Person();
		p1.setAge(11);
		p1.setEmail("aa@163.com");
		p1.setLastName("AA");
		
		Person p2 = new Person();
		p2.setAge(12);
		p2.setEmail("bb@163.com");
		p2.setLastName("BB");
		
		System.out.println(personService.getClass().getName());
		personService.savePersons(p1, p2);
	}
	
	@Test
	public void testDataSource() throws SQLException {
		DataSource dataSource = ctx.getBean(DataSource.class);
		System.out.println(dataSource.getConnection());
	}

}

posted @ 2022-01-24 10:04  KeepArlen  阅读(139)  评论(0)    收藏  举报