JPA初始
以下内容引用尚硅谷,如有侵权请联系删除
第一章 JPA概述






第二章 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

2.4 @Basic

2.5 @Column

@Transient
表示该属性并非一个到数据库表的字段的映射,ORM框架将忽略该属性.
如果一个属性并非数据库表的字段映射,就务必将其标示为Transient,否则,ORM框架默认其注解为@Basic
@Temporal
在核心的Java API中并没有定义Date类型的精度(temporal precision).而在数据库中,表示Date类型的数据有DATE, TIME,和TIMESTAMP三种精度(即单纯的日期,时间,或者两者兼备).在进行属性映射时可使用
@Temporal注解来调整精度.
2.6 用table来生成主键详解


第三章 JPA API
3.1 Persistence

3.2 EntityManagerFactory

3.3 EntityManager








3.4 EntityTransaction
EntityTransaction接口用来管理资源层实体管理器的事务操作。
通过调用实体管理器的getTransaction方法获得其实例。


第四章 映射关联关系
4.1 双向一对多及多对一映射

4.2 双向一对一映射

4.3 双向1-1不延迟加载的问题
通过Manager查询Department,不管Manager的Department属性上的@OneToOne注解上有没有延迟加载属性,都不管用的,因为外键字段是定义在Department表中的

4.4 双向多对多关联关系

第四章 代码总结

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工程过程





导入依赖
<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>
第六章 二级缓存代码示例

<?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 介绍





7.2 select语句
select-from

查询所有实体


where子句




查询部分属性

使用Hibernate的查询缓存

oraer by子句

group by子句与聚合查询

having子句

关联查询


子查询

JPQL函数


update语句

delete语句

第七章 代码总结

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


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

浙公网安备 33010602011771号