JPA 基础

数据库驱动 ==> JDBC 规范 ==> ORM 框架 ==> JPA 规范 ==> spring-data-jpa

ORM 思想

JPA 的使用步骤

jpa 依赖

<properties>
<project.hibernate.version>5.4.2.Final</project.hibernate.version>
</properties> <!-- hibernate对jpa的支持包 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${project.hibernate.version}</version>
</dependency> <!-- c3p0 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>${project.hibernate.version}</version>
</dependency> <!-- Mysql and MariaDB -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>

jpa 的持久化配置

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
<!-- 持久化单元 -->
<persistence-unit name="myJPA" transaction-type="RESOURCE_LOCAL">
<!-- JPA 的实现者 -->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> <properties>
<!-- 数据库信息
驱动 javax.persistence.jdbc.driver
数据库地址 javax.persistence.jdbc.url
用户名 javax.persistence.jdbc.user
密码 javax.persistence.jdbc.password
-->
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:mysql:///jpa_db" />
<property name="javax.persistence.jdbc.user" value="root" />
<property name="javax.persistence.jdbc.password" value="root" /> <!-- jpa 实现者的配置
显示 sql : hibernate.show_sql
格式化 sql : hibernate.format_sql
创建表: hibernate.hbm2ddl.auto 库必须存在,hibernate 不会自动创建库
create: 运行时创建,有则先删除再创建
update: 运行时创建,有则不创建
none: 不创建
-->
<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.mozq.jpa.domain;

import org.hibernate.annotations.GeneratorType;

import javax.persistence.*;

@Entity
@Table
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long custId;
@Column
private String custName;
@Column
private String custSource;
@Column
private String custLevel;
@Column
private String custIndustry;
@Column
private String custPhone;
@Column
private String custAddress;
//省略构造器和 get/set
}

使用 jpa 的 API 进行操作

JPA实体的四种状态 https://www.jianshu.com/p/636954880af8

JPA中的实体对象拥有四种状态:

  • 瞬时状态(transient)
  • 持久状态(persistent)
  • 游离状态(detached)
  • 删除状态 (deleted)

瞬时状态

瞬时状态的实体就是一个普通的java对象,和持久化上下文无关联,数据库中也没有数据与之对应。

托管状态

使用 EntityManager 进行 find 或者 persist 操作返回的对象即处于托管状态,此时该对象已经处于持久化上下文中,因此任何对于该实体的更新都会同步到数据库中。

游离状态

当事务提交后,处于托管状态的对象就转变为了游离状态。此时该对象已经不处于持久化上下文中,因此任何对于该对象的修改都不会同步到数据库中。但是数据库中有这个对象对应的记录。

删除状态

当调用EntityManger对实体进行delete后,该实体对象就处于删除状态。其本质也就是一个瞬时状态的对象。

持久:处于持久的对象被 EntityManager 管理,当事务被提交时,则对持久对象的任何修改都将同步到数据库中。

public interface EntityManager {
/*
瞬时对象
游离对象将报异常
*/
void persist(Object var1); // 对象持久化,交给 EntityManager 管理。数据库中必须不存在。瞬时 ==> 持久
<T> T merge(T var1);// 根据 id 是否存在,插入新对象或更新现有对象。瞬时 ==> 持久 / 游离 ==> 持久 void remove(Object var1);
<T> T find(Class<T> entityClass, Object id);// 立即加载,返回真实对象
<T> T getReference(Class<T> entityClass, Object id);// 延迟加载,返回代理对象 void flush();
/* obj 必须是受管对象,用于将数据库数据同步到受管对象,如果是其他状态的对象将抛异常。*/
void refresh(Object var1);
void clear();
void detach(Object var1); void close();//关闭
EntityTransaction getTransaction();// 获取事务对象
}
# void refresh(Object var1);
java.lang.IllegalArgumentException: Entity not managed
# persist 方法异常
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: com.mozq.jpa.domain.Customer Customer customer = new Customer();
customer.setCustId(1L);
customer.setCustName("刘备");
em.persist(customer);//此时数据库中存在 1L 记录,报错。
@Test
public void testSave(){
// Persistence 创建实体类管理器工厂
EntityManagerFactory factory = Persistence.createEntityManagerFactory("myJPA");
// 实体类管理器
EntityManager em = factory.createEntityManager();
// 事务对象
EntityTransaction tx = em.getTransaction();
tx.begin(); // CRUD
Customer customer = new Customer();
customer.setCustName("刘备"); em.persist(customer); // 保存 tx.commit();
// 释放资源
em.close();
factory.close();
}

JPQL 查询

// 查询全部
Query query = em.createQuery("from Customer");
List resultList = query.getResultList();
System.out.println(resultList);
// 排序
Query query = em.createQuery("from Customer order by custAddress desc ,custName asc, custId");
List resultList = query.getResultList();
/*
order by
customer0_.custAddress desc,
customer0_.custName asc,
customer0_.custId
*/
// 分页
Query query = em.createQuery("from Customer order by custId");
query.setFirstResult(2);
query.setMaxResults(3);
/*
order by
customer0_.custId limit ?, ?
*/

Hibernate 主键生成策略和创建表策略

public enum GenerationType {
TABLE,
SEQUENCE,
IDENTITY,
AUTO; private GenerationType() {
}
}
hibernate.hbm2ddl.auto create/update/none
# <property name="hibernate.hbm2ddl.auto" value="create" /> # 先删除表,再创建表
# @GeneratedValue(strategy = GenerationType.IDENTITY)
drop table if exists Customer
create table Customer (
custId bigint not null auto_increment, # 使用自增主键,生成的 sql 不会有主键字段。需要数据库支持自增。
custAddress varchar(255),
custIndustry varchar(255),
custLevel varchar(255),
custName varchar(255),
custPhone varchar(255),
custSource varchar(255),
primary key (custId)
) engine=InnoDB
insert
into
Customer
(custAddress, custIndustry, custLevel, custName, custPhone, custSource)
values
(?, ?, ?, ?, ?, ?)
# <property name="hibernate.hbm2ddl.auto" value="update" />
# @GeneratedValue(strategy = GenerationType.IDENTITY) # 使用自增主键,生成的 sql 不会有主键字段。需要数据库支持自增。
create table Customer ( # 如果表不存在则会发送创建表的语句。
custId bigint not null auto_increment,
custAddress varchar(255),
custIndustry varchar(255),
custLevel varchar(255),
custName varchar(255),
custPhone varchar(255),
custSource varchar(255),
primary key (custId)
) engine=InnoDB
insert
into
Customer
(custAddress, custIndustry, custLevel, custName, custPhone, custSource)
values
(?, ?, ?, ?, ?, ?)

GenerationType.AUTO + create

drop table if exists Customer
drop table if exists hibernate_sequence create table Customer (
custId bigint not null,
custAddress varchar(255),
custIndustry varchar(255),
custLevel varchar(255),
custName varchar(255),
custPhone varchar(255),
custSource varchar(255),
primary key (custId)
) engine=InnoDB create table hibernate_sequence (
next_val bigint
) engine=InnoDB insert into hibernate_sequence values ( 1 ) select
next_val as id_val
from
hibernate_sequence for update 锁 update
hibernate_sequence
set
next_val= ?
where
next_val=? insert into
Customer
(custAddress, custIndustry, custLevel, custName, custPhone, custSource, custId)
values
(?, ?, ?, ?, ?, ?, ?)

JPA

Caused by: org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): com.mozq.jpa.domain.Customer

最新文章

  1. Atitit.web ui &#160;组件化 vs &#160;mvc
  2. HTML &lt;a&gt; download 属性,点击链接来下载图片
  3. First Missing Positive &amp;&amp; missing number
  4. 理解Ruby中的作用域
  5. flask-uploads扩展的使用笔记
  6. Vue2.0的通用组件
  7. 【Merge K Sorted Lists】cpp
  8. 通用块层、IO调度层以及设备驱动层的数据结构
  9. CentOS+Apache+php无法访问redis的解决方法
  10. IE 兼容性问题
  11. 三、Dockerfile的说明和编写
  12. python中logger模块的应用
  13. Android 组件的三种点击事件写法
  14. 廖雪峰 JavaScript 学习笔记(字符串、数组和对象)
  15. iptables防DDOS攻击和CC攻击设置
  16. IIS 设置404页面 显示系统找不到指定的文件
  17. GIF动画录制工具(写教程时用的比较小巧的gif工具)
  18. EasyAACEncoder海思/ARM平台优化G711、G726转AAC的CPU占用高问题
  19. css animation动画
  20. hdu 1754 线段树 单点更新 动态区间最大值

热门文章

  1. python总结十一
  2. WC 2008 观光计划(斯坦纳树)
  3. Airtest网易开源的一款UI自动化测试工具
  4. http与tcp,udp的区别
  5. netcore与ef资料收集
  6. 聊聊Runloop
  7. Python 发送企业微信消息
  8. Mocha测试框架,保证代码质量
  9. Intellij IDEA的安装教程
  10. Qt 的两个许可证区别分析:LGPL 和商业协议