JPA 的简单使用
1 JPA
1.1 JPA的相关概念
JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。
JPA的宗旨是为POJO提供持久化标准规范。总的来说,JPA包括以下3方面的技术:
ORM映射元数据,JPA支持XML和JDK 5.0注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中;
JPA 的API,用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,开发者从繁琐的JDBC和SQL代码中解脱出来。
查询语言,这是持久化操作中很重要的一个方面,通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。
1.2 什么是ORM
orm 是指,通过一定的方法让数据库中的表和pojo建立某种联系,我们通过操作pojo就能达到操作pojo的目的
2 JPA 入门程序
2.1 JPA 的核心配置文件
-
在根目录下创建一个META-INF 文件夹
-
在META-INF 文件夹下创建一个persistence.xml 文件
-
编写persistence.xml 文件
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<!--持久化单元配置
name:持久化单元名称
transacti
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<!--持久化单元配置
name:持久化单元名称
transaction-type:事务模式。RESOURCE_LOCAL:本地事务 JTA:分布式事务
-->
<persistence-unit name="myJpa" transaction-type="RESOURCE_LOCAL">
<!--配置JPA提供商-->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<!--连接数据库配置-->
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="root"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/ssh"/>
<!--jpa实现方的配置-->
<!--是否打印sql语句-->
<property name="hibernate.show_sql" value="true"/>
<!--是否格式化sql语句-->
<property name="hibernate.format_sql" value="true"/>
<!--是否自动创建数据库表
可选值:create、update、none
create:程序自动创建数据库表,如果表存在则先删除后创建
update:程序自动创建数据库表,如果表存在则不创建。
none:不会创建表
-->
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
</persistence>
2.2 依赖
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<hibernate.version>4.3.8.Final</hibernate.version>
<mysql.version>5.1.40</mysql.version>
<junit.version>4.12</junit.version>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<!-- 必须添加 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>jpa-single-table</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
2.3 创建POJO 和 表
package com.wlqk.pojo;
import javax.persistence.*;
@Entity
@Table(name = "cst_customer")
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="cust_id")
private long custId;
@Column(name="cust_name")
private String custName;
@Column(name="cust_source")
private String custSource;
@Column(name="cust_industry")
private String custIndustry;
@Column(name="cust_level")
private String custLevel;
@Column(name="cust_address")
private String custAddress;
@Column(name="cust_phone")
private String custPhone;
public long getCustId() {
return custId;
}
public void setCustId(long custId) {
this.custId = custId;
}
public String getCustName() {
return custName;
}
public void setCustName(String custName) {
this.custName = custName;
}
public String getCustSource() {
return custSource;
}
public void setCustSource(String custSource) {
this.custSource = custSource;
}
public String getCustIndustry() {
return custIndustry;
}
public void setCustIndustry(String custIndustry) {
this.custIndustry = custIndustry;
}
public String getCustLevel() {
return custLevel;
}
public void setCustLevel(String custLevel) {
this.custLevel = custLevel;
}
public String getCustAddress() {
return custAddress;
}
public void setCustAddress(String custAddress) {
this.custAddress = custAddress;
}
public String getCustPhone() {
return custPhone;
}
public void setCustPhone(String custPhone) {
this.custPhone = custPhone;
}
@Override
public String toString() {
return "Customer{" +
"custId=" + custId +
", custName='" + custName + '\'' +
", custSource='" + custSource + '\'' +
", custIndustry='" + custIndustry + '\'' +
", custLevel='" + custLevel + '\'' +
", custAddress='" + custAddress + '\'' +
", custPhone='" + custPhone + '\'' +
'}';
}
}
```
```
Create Table
CREATE TABLE `cst_customer` (
`cust_id` bigint(20) NOT NULL AUTO_INCREMENT,
`cust_address` varchar(255) DEFAULT NULL,
`cust_industry` varchar(255) DEFAULT NULL,
`cust_level` varchar(255) DEFAULT NULL,
`cust_name` varchar(255) DEFAULT NULL,
`cust_phone` varchar(255) DEFAULT NULL,
`cust_source` varchar(255) DEFAULT NULL,
PRIMARY KEY (`cust_id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8
2.4 测试代码
public class CustomerTest {
@Test
public void testAddCustomer() throws Exception {
EntityManagerFactory factory = Persistence.createEntityManagerFactory("myJpa");
EntityManager entityManager = factory.createEntityManager();
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
Customer customer = new Customer();
customer.setCustName("张三");
customer.setCustAddress("北京");
customer.setCustIndustry("旅游");
customer.setCustLevel("vip");
customer.setCustPhone("13600132258");
customer.setCustSource("网络");
entityManager.persist(customer);
transaction.commit();
entityManager.close();
factory.close();
}
}
3 详解
3.1 注解详解
@Entity 作用:指定当前类是实体类。
@Table 作用:指定实体类和表之间的对应关系。
属性: name:指定数据库表的名称
@Id 作用:指定当前字段是主键。
@GeneratedValue 作用:指定主键的生成方式。。
属性:strategy :指定主键生成策略。 主要有四种
IDENTITY:主键由数据库自动生成(主要是自动增长型
SEQUENCE:根据底层数据库的序列来生成主键,条件是数据库支持序列
AUTO:主键由程序控制
TABLE:使用一个特定的数据库表格来保存主键
@Column 作用:指定实体类属性和数据库表之间的对应关系
属性: name:指定数据库表的列名称。
unique:是否唯一
nullable:是否可以为空
inserttable:是否可以插入
updateable:是否可以更新
columnDefinition: 定义建表时创建此列的DDL
secondaryTable: 从表名。如果此列不建在主表上(默认建在主表),该属性定 义该列所在从表的名字
3.2 对象使用方法
1.Persistence
Persistence对象主要作用是用于获取EntityManagerFactory对象的 。通过调用该类的createEntityManagerFactory静态方法,根据配置文件中持久化单元名称创建EntityManagerFactory。
//1. 创建 EntitymanagerFactory
@Test
String unitName = “myJpa”;
EntityManagerFactory factory= Persistence.createEntityManagerFactory(unitName);
//unitName 对应于配置文件中的
2.EntityManagerFactory
EntityManagerFactory 接口主要用来创建 EntityManager 实例
//创建实体管理类
EntityManager em = factory.createEntityManager();
由于EntityManagerFactory 是一个线程安全的对象(即多个线程访问同一个EntityManagerFactory 对象不会有线程安全问题),并且EntityManagerFactory 的创建极其浪费资源,所以在使用JPA编程时,我们可以对EntityManagerFactory 的创建进行优化,只需要做到一个工程只存在一个EntityManagerFactory 即可
3.EntityManager
在 JPA 规范中, EntityManager是完成持久化操作的核心对象。实体类作为普通 java对象,只有在调用 EntityManager将其持久化后才会变成持久化对象。EntityManager对象在一组实体类与底层数据源之间进行 O/R 映射的管理。它可以用来管理和更新 Entity Bean, 根椐主键查找 Entity Bean, 还可以通过JPQL语句查询实体。
我们可以通过调用EntityManager的方法完成获取事务,以及持久化数据库的操作
getTransaction : //获取事务对象
persist : //保存操作
merge : //更新操作
remove : //删除操作
find/getReference ://根据id查询
4.EntityTransaction
在 JPA 规范中, EntityTransaction是完成事务操作的核心对象,对于EntityTransaction在我们的java代码中承接的功能比较简单
begin: //开启事务
commit: //提交事务
rollback://回滚事务
4 JPA 的CRUD
import com.wlqk.pojo.Customer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import javax.persistence.*;
import java.util.List;
/**
* @Description:
* @Author: zc
* @CreateDate: 2019/2/3$ 15:45$
*/
public class Demo1 {
private EntityManagerFactory factory = null;
private EntityManager entityManager = null;
private EntityTransaction transaction = null;
@Before
public void before(){
factory = Persistence.createEntityManagerFactory("myJpa");
entityManager = factory.createEntityManager();
transaction = entityManager.getTransaction();
transaction.begin();
}
@After
public void after(){
transaction.commit();
entityManager.close();
factory.close();
}
//添加
@Test
public void add(){
Customer customer = new Customer();
customer.setCustName("赵六");
customer.setCustAddress("河北");
customer.setCustIndustry("广州");
customer.setCustLevel("vip");
customer.setCustPhone("1360015478478");
customer.setCustSource("网络");
entityManager.persist(customer);
}
//删除
@Test
public void delete(){
try{
//获取数据
Customer customer = entityManager.find(Customer.class, 1L);
entityManager.remove(customer);
}catch (Exception e){
transaction.rollback();
}
}
//修改
@Test
public void update(){
try {
Customer customer = entityManager.find(Customer.class, 2L);
customer.setCustName("武则天");
entityManager.merge(customer);
}catch (Exception e){
transaction.rollback();
}
}
//测试即时加载和懒加载
@Test //即时加载
public void find(){
try{
Customer customer = entityManager.find(Customer.class, 2L);
System.out.println(customer);
}catch (Exception e){
transaction.rollback();
}
}
@Test //懒加载,,没有使用,就没有查询
public void reference(){
Customer customer = entityManager.getReference(Customer.class, 2L);
// System.out.println(customer);
}
//查询全部
@Test
public void queryAll(){
//编写sql语句
String sql = "from Customer";
Query query = entityManager.createQuery(sql);
List<Customer> list = query.getResultList();
for (Customer customer : list) {
System.out.println(customer);
}
}
//分页查询
@Test
public void pageQuery(){
//编写sql语句
String sql = "from Customer";
Query query = entityManager.createQuery(sql);
query.setFirstResult(0);
query.setMaxResults(2);
List<Customer> list = query.getResultList();
for (Customer customer : list) {
System.out.println(customer);
}
}
/*---------待条件查询---------*/
//模糊查询
@Test
public void likeQuery(){
//JPQL查询语句
String sql = "from Customer where custName like ?";
//创建查询对象
Query query = entityManager.createQuery(sql);
//设置查询条件。参数1:参数的索引从1开始,参数2:查询参数
query.setParameter(1,"%则%");
List<Customer> resultList = query.getResultList();
for (Customer customer : resultList) {
System.out.println(customer);
}
}
//排序查询
@Test
public void orderBy(){
String sql = "from Customer order by ? desc";