ORM概述

ORM(Object-Relational Mapping) 表示对象关系映射。在面向对象的软件开发中,通过ORM,就可以把对象映射到关系型数据库中。只要有一套程序能够做到建立对象与数据库的关联,操作对象就可以直接操作数据库数据,就可以说这套程序实现了ORM对象关系映射

简单的说:ORM就是建立实体类和数据库表之间的关系,从而达到操作实体类就相当于操作数据库表的目的。

为什么要使用ORM

当实现一个应用程序时(不使用O/R Mapping),我们可能会写特别多数据访问层的代码,从数据库保存数据、修改数据、删除数据,而这些代码都是重复的。而使用ORM则会大大减少重复性代码。对象关系映射(Object Relational Mapping,简称ORM),主要实现程序对象到关系数据库数据的映射。

常见的ORM框架

Mybatis(ibatis)、hibernate、Jpa

hibernate与JPA的概述

hibernate概述

Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。

JPA概述

JPA的全称是Java Persistence API, 即Java 持久化API,是SUN公司推出的一套基于ORM的规范,内部是由一系列的接口和抽象类构成。

JPA通过JDK 5.0注解描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。

JPA的优势

1. 标准化

JPA 是 JCP 组织发布的 Java EE 标准之一,因此任何声称符合 JPA 标准的框架都遵循同样的架构,提供相同的访问API,这保证了基于JPA开发的企业应用能够经过少量的修改就能够在不同的JPA框架下运行。

2. 容器级特性的支持

JPA框架中支持大数据集、事务、并发等容器级事务,这使得 JPA 超越了简单持久化框架的局限,在企业应用发挥更大的作用。

3. 简单方便

JPA的主要目标之一就是提供更加简单的编程模型:在JPA框架下创建实体和创建Java 类一样简单,没有任何的约束和限制,只需要使用 javax.persistence.Entity进行注释,JPA的框架和接口也都非常简单,没有太多特别的规则和设计模式的要求,开发者可以很容易的掌握。JPA基于非侵入式原则设计,因此可以很容易的和其它框架或者容器集成

4. 查询能力

JPA的查询语言是面向对象而非面向数据库的,它以面向对象的自然语法构造查询语句,可以看成是Hibernate HQL的等价物。JPA定义了独特的JPQL(Java Persistence Query Language),JPQL是EJB QL的一种扩展,它是针对实体的一种查询语言,操作对象是实体,而不是关系数据库的表,而且能够支持批量更新和修改、JOIN、GROUP BY、HAVING 等通常只有 SQL 才能够提供的高级查询特性,甚至还能够支持子查询。

5. 高级特性

JPA 中能够支持面向对象的高级特性,如类之间的继承、多态和类之间的复杂关系,这样的支持能够让开发者最大限度的使用面向对象的模型设计企业应用,而不需要自行处理这些特性在关系数据库的持久化。

JPA与hibernate的关系

JPA规范本质上就是一种ORM规范,注意不是ORM框架——因为JPA并未提供ORM实现,它只是制订了一些规范,提供了一些编程的API接口,但具体实现则由服务厂商来提供实现。

JPA和Hibernate的关系就像JDBC和JDBC驱动的关系,JPA是规范,Hibernate除了作为ORM框架之外,它也是一种JPA实现。JPA怎么取代Hibernate呢?JDBC规范可以驱动底层数据库吗?答案是否定的,也就是说,如果使用JPA规范进行数据库操作,底层需要hibernate作为其实现类完成数据持久化工作。

案例介绍

此处使用hibernate 5.4.10.Final   maven 3.6.3

导入依赖

 <dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.4.10.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>5.4.10.Final</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>

创建配置文件persistence.xml

注意:配置文件的目录

在java工程的src路径下创建一个名为META-INF的文件夹,在此文件夹下创建一个名为persistence.xml的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0"> <!--
需要配置persistence-unit 节点
持久化单元
name : 持久化单元名称
transaction-type : 事务管理方式
RESOURCE_LOCAL : 本地事务管理
JTA : 分布式事务管理
-->
<persistence-unit name="myJpa" transaction-type="RESOURCE_LOCAL">
<!-- jpa的实现方式 -->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<!--
配置数据库的信息
用户名 : javax.persistence.jdbc.user
密码 : javax.persistence.jdbc.password
连接地址 : javax.persistence.jdbc.url
驱动 : javax.persistence.jdbc.driver
-->
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="root"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/jpa"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/> <!--配置jpa实现方(hibernate)的配置信息
显示sql : false|true
自动创建数据库表 : hibernate.hbm2ddl.auto
create : 程序运行时创建数据库表(如果有表,先删除表再创建)
update :程序运行时创建表(如果有表,不会创建表)
none :不会创建表 -->
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties> </persistence-unit> </persistence>

创建实体类

package com.ytfs.entity;

import javax.persistence.*;
import java.io.Serializable; /**
* @Classname Customer
* @Description TODO(客户实体类)
* @Date 2020/4/28 22:34
* @Created by ytfs
* 客户的实体类
* 配置映射关系
* 1.实体类和表的映射关系
* @Entity:声明实体类
* @Table : 配置实体类和表的映射关系
* name : 配置数据库表的名称
* 2.实体类中属性和表中字段的映射关系
*
*/ @Entity
@Table(name = "cst_customer")
public class Customer implements Serializable {
/**
* @Id:声明主键的配置
* @GeneratedValue:配置主键的生成策略
* strategy
* GenerationType.IDENTITY :自增,mysql
* * 底层数据库必须支持自动增长(底层数据库支持的自动增长方式,对id自增)
* GenerationType.SEQUENCE : 序列,oracle
* * 底层数据库必须支持序列
* GenerationType.TABLE : jpa提供的一种机制,通过一张数据库表的形式帮助我们完成主键自增
* GenerationType.AUTO : 由程序自动的帮助我们选择主键生成策略
* @Column:配置属性和字段的映射关系
* name:数据库表中字段的名称
*/
@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 + '\'' +
'}';
}
}

参数的解释

        @Entity
作用:指定当前类是实体类。
@Table
作用:指定实体类和表之间的对应关系。
属性:
name:指定数据库表的名称
@Id
作用:指定当前字段是主键。
@GeneratedValue
作用:指定主键的生成方式。。
属性:
strategy :指定主键生成策略。
@Column
作用:指定实体类属性和数据库表之间的对应关系
属性:
name:指定数据库表的列名称。
unique:是否唯一
nullable:是否可以为空
inserttable:是否可以插入
updateable:是否可以更新
columnDefinition: 定义建表时创建此列的DDL
secondaryTable: 从表名。如果此列不建在主表上(默认建在主表),该属性定义该列所在从表的名字搭建开发环境[重点]

创建JPA的连接工具类

package com.ytfs.utils;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence; /**
* @Classname Jpautil
* @Description TODO(Jpa实体类管理工厂)
* @Date 2020/4/28 23:38
* @Created by ytfs
*/
public class JpaUtil { //线程安全的
private static final EntityManagerFactory FACTORY; static { /*这里的实体类工厂的persistenceUnitName是配置文件中
<persistence-unit name="myJpa" transaction-type="RESOURCE_LOCAL">
*/
FACTORY = Persistence.createEntityManagerFactory("myJpa"); } /**
* 返回实体类管理对象
* @return
*/
public static EntityManager getEM(){
return FACTORY.createEntityManager();
}
}

创建测试类

package com.ytfs;

import com.ytfs.entity.Customer;
import com.ytfs.utils.JpaUtil;
import org.junit.Test; import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction; /**
* @Classname test
* @Description TODO(JPA测试)
* @Date 2020/4/28 22:58
* @Created by ytfs
*/ public class test { /**
* 保存客户
*/
@Test
public void testSave() {
/* //创建实体类的工厂管理对象
EntityManagerFactory factory = Persistence.createEntityManagerFactory("myJpa"); //创建实体类管理对象
EntityManager entityManager = factory.createEntityManager();*/ EntityManager entityManager = JpaUtil.getEM();
//开启事务
entityManager.getTransaction().begin();
//创建一个对象
Customer customer = new Customer();
customer.setCustName("张三");
customer.setCustAddress("重庆市沙坪坝区");
//保存对象
entityManager.persist(customer); //提交事务
entityManager.getTransaction().commit(); //释放资源
entityManager.close();
//factory.close(); 利用工具类之后就不用关闭工厂对象,因为线程安全只需要一个,后面的还会一直用
} /**
* @throws
* @description find方式通过Id查询
* @author 雨听风说
* @updateTime 2020/4/29 13:03
* 使用find方法查询:
* 1.查询的对象就是当前客户对象本身
* 2.在调用find方法的时候,就会发送sql语句查询数据库
* <p>
* 立即加载
*/
@Test
public void testFind() { //通过工具类获取实体类管理对象
EntityManager em = JpaUtil.getEM(); //获取事务对象
EntityTransaction tx = em.getTransaction();
//开启事务
tx.begin(); //通过实体类管理对象查询
Customer customer = em.find(Customer.class, 1L); //customer.soutv
System.out.println("customer = " + customer); //提交事务
tx.commit(); //释放资源
em.close();
} /**
* @param
* @return
* @throws
* @description 通过事务管理对象的get方式通过Id查询
* @author 雨听风说
* @updateTime 2020/4/29 13:13
* getReference方法
* 1.获取的对象是一个动态代理对象
* 2.调用getReference方法不会立即发送sql语句查询数据库
* * 当调用查询结果对象的时候,才会发送查询的sql语句:什么时候用,什么时候发送sql语句查询数据库
* <p>
* 延迟加载(懒加载)
* * 得到的是一个动态代理对象
* * 什么时候用,什么使用才会查询
*/ @Test
public void testGetRefrence() { //通过工具类获取实体类管理对象
EntityManager em = JpaUtil.getEM(); //获取事务对象并开启事务
EntityTransaction tx = em.getTransaction();
tx.begin(); //通过实体类对象查询
Customer customer = em.getReference(Customer.class, 1L); System.out.println("customer = " + customer); //提交事务
tx.commit(); //释放资源
em.close();
} /**
* @param
* @return
* @throws
* @description 删除对象
* @author 雨听风说
* @updateTime 2020/4/29 13:17
*/
@Test
public void testRemove() { //通过工具类获取实体类管理对象
EntityManager em = JpaUtil.getEM(); //获取事务对象并开启事务
EntityTransaction tx = em.getTransaction();
tx.begin(); //通过实体类对象删除
//i 通过id查询需要删除的对象
Customer customer = em.find(Customer.class, 1L);
//ii 调用remove方法,传入需要删除的对象
em.remove(customer);
//提交事务
tx.commit(); //释放资源
em.close(); }
/**
* @param
* @return
* @throws
* @description 更新对象
* @author 雨听风说
* @updateTime 2020/4/29 13:17
*/
@Test
public void testUpdate() { //通过工具类获取实体类管理对象
EntityManager em = JpaUtil.getEM(); //获取事务对象并开启事务
EntityTransaction tx = em.getTransaction();
tx.begin(); //通过实体类对象更新
//i 通过id查询需要更新的对象
Customer customer = em.find(Customer.class, 2L);
customer.setCustName("电动小马达"); //ii 调用merge方法,传入需要更新的对象
em.merge(customer); //提交事务
tx.commit(); //释放资源
em.close();
}
}

JPQL查询(Java Persistence Query Language)

基于首次在EJB2.0中引入的EJB查询语言(EJB QL),Java持久化查询语言(JPQL)是一种可移植的查询语言,旨在以面向对象表达式语言的表达式,将SQL语法和简单查询语义绑定在一起·使用这种语言编写的查询是可移植的,可以被编译成所有主流数据库服务器上的SQL。

其特征与原生SQL语句类似,并且完全面向对象,通过类名和属性访问,而不是表名和表的属性。

测试

package com.ytfs;

import com.ytfs.utils.JpaUtil;
import org.junit.Test; import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.util.List; /**
* @Classname JpqlTest
* @Description TODO(Jpql的测试案例)
* @Date 2020/4/29 13:22
* @Created by ytfs
*/ public class JpqlTest { /**
* jpql查询全部
* jqpl:from com.ytfs.entity.Customer
* sql:SELECT * FROM cst_customer
*/
@Test
public void testFindAll() { //通过工具类获取实体类管理对象
EntityManager em = JpaUtil.getEM(); //通过实体类管理对象获取事务对象并开启事务
em.getTransaction().begin(); //书写jpql语句
String jpql = "from Customer"; //通过实体类管理对象执行查询
Query query = em.createQuery(jpql); //获取查询结果
List list = query.getResultList(); //遍历输出
list.stream().forEach(System.out::println); //提交事务
em.getTransaction().commit(); //释放资源
em.close(); } /**
* 排序查询: 倒序查询全部客户(根据id倒序)
* sql:SELECT * FROM cst_customer ORDER BY cust_id DESC
* jpql:from Customer order by custId desc
*
* 进行jpql查询
* 1.创建query查询对象
* 2.对参数进行赋值
* 3.查询,并得到返回结果
*/
@Test
public void test() { //通过工具类获取实体类管理对象
EntityManager em = JpaUtil.getEM(); //通过实体类管理对象获取事务对象并开启事务
em.getTransaction().begin(); //书写jpql语句
String jpql = "from Customer order by custId desc"; //通过实体类管理对象执行查询
Query query = em.createQuery(jpql); //获取查询结果
List list = query.getResultList(); //遍历输出
list.stream().forEach(System.out::println); //提交事务
em.getTransaction().commit(); //释放资源
em.close(); } /**
* 使用jpql查询,统计客户的总数
* sql:SELECT COUNT(cust_id) FROM cst_customer
* jpql:select count(custId) from Customer
*/
@Test
public void testCount() { //通过工具类获取实体类管理对象
EntityManager em = JpaUtil.getEM(); //通过实体类管理对象获取事务对象并开启事务
em.getTransaction().begin(); //书写jpql语句
String jpql = "select count(custId) from Customer"; //通过实体类管理对象执行查询
Query query = em.createQuery(jpql); //ii.对参数赋值
//iii.发送查询,并封装结果 /**
* getResultList : 直接将查询结果封装为list集合
* getSingleResult : 得到唯一的结果集
*/
Object singleResult = query.getSingleResult(); //遍历输出
System.out.println("singleResult = " + singleResult); //提交事务
em.getTransaction().commit(); //释放资源
em.close(); } /**
* 分页查询
* sql:select * from cst_customer limit 0,2
* jqpl : from Customer
*/ @Test
public void testByPage() { //通过工具类获取实体类管理对象
EntityManager em = JpaUtil.getEM(); //通过实体类管理对象获取事务对象并开启事务
em.getTransaction().begin(); //书写jpql语句
String jpql = "from Customer"; //通过实体类管理对象执行查询
Query query = em.createQuery(jpql); //ii.对参数赋值
//开始的索引
query.setFirstResult(0);
//每页的条数
query.setMaxResults(2);
//iii.发送查询,并封装结果 /**
* getResultList : 直接将查询结果封装为list集合
* getSingleResult : 得到唯一的结果集
*/
//获取查询结果
List list = query.getResultList(); //遍历输出
list.stream().forEach(System.out::println); //提交事务
em.getTransaction().commit(); //释放资源
em.close(); } /**
* 条件查询
* 案例:查询客户名称包含‘小马’的客户
* sql:SELECT * FROM cst_customer WHERE cust_name LIKE ?1
* jpql : from Customer where custName like ?1
*/ @Test
public void testByCondition() { //通过工具类获取实体类管理对象
EntityManager em = JpaUtil.getEM(); //通过实体类管理对象获取事务对象并开启事务
em.getTransaction().begin(); //书写jpql语句
String jpql = "from Customer where custName like ?1 "; //通过实体类管理对象执行查询
Query query = em.createQuery(jpql); //ii.对参数赋值
//第一个参数:占位符的索引位置(jpql语句后的数字代表,直接问号出现异常),第二个参数:取值
query.setParameter(1, "%小马%");
//iii.发送查询,并封装结果 /**
* getResultList : 直接将查询结果封装为list集合
* getSingleResult : 得到唯一的结果集
*/
//获取查询结果
List list = query.getResultList(); //遍历输出
list.stream().forEach(System.out::println); //提交事务
em.getTransaction().commit(); //释放资源
em.close(); }
}

JPA与hibernate-------JPA的更多相关文章

  1. ssh(sturts2_spring_hibernate) 框架搭建之JPA代替hibernate

    一.JPA用来替代hibernate ⒈JPA的全称是JAVA Persistence API.指的是JPA通过注解或者是XML描述对象—关系表的映射关系,并且将运行的实体对象持久化数据库中. ⒉JP ...

  2. JPA和hibernate的关系

    实际上,JPA的标准的定制是hibernate作者参与定制的,所以JPA是hibernate的一个总成,可以这么理解

  3. JPA入门例子(采用JPA的hibernate实现版本)

    (1).JPA介绍: JPA全称为Java Persistence API ,Java持久化API是Sun公司在Java EE 5规范中提出的Java持久化接口.JPA吸取了目前Java持久化技术的优 ...

  4. spring data jpa hibernate jpa 三者之间的关系

    JPA规范与ORM框架之间的关系是怎样的呢? JPA规范本质上就是一种ORM规范,注意不是ORM框架——因为JPA并未提供ORM实现,它只是制订了一些规范,提供了一些编程的API接口,但具体实现则由服 ...

  5. JPA与Hibernate的关系

    1.JPA JPA全称: Java Persistence API  JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中.  JPA的出现?  JPA ...

  6. Hibernate+JPA (EntityMange讲解)

    近年来ORM(Object-Relational Mapping)对象关系映射,即实体对象和数据库表的映射)技术市场人声音鼎沸,异常热闹, Sun在充分吸收现有的优秀ORM框架设计思想的基础上,制定了 ...

  7. JPA和Hibernate的区别

    JPA Java Persistence API,是Java EE 5的标准ORM接口,也是ejb3规范的一部分. Hibernate,当今很流行的ORM框架,是JPA的一个实现,但是其功能是JPA的 ...

  8. spring+hibernate+jpa+Druid的配置文件,spring整合Druid

    spring+hibernate+jpa+Druid的配置文件 spring+hibernate+jpa+Druid的完整配置 spring+hibernate+jpa+Druid的数据源配置 spr ...

  9. JPA入门例子(采用JPA的hibernate实现版本) 转

    JPA入门例子(采用JPA的hibernate实现版本) jpahibernate数据库jdbcjava框架(1).JPA介绍: JPA全称为Java Persistence API ,Java持久化 ...

  10. Hibernate+JPA

    参考链接:http://blog.163.com/hero_213/blog/static/398912142010312024809 近年来ORM(Object-Relational Mapping ...

随机推荐

  1. android学习笔记——使用QuickContactBadge关联联系人

    本文大部分内容来自<疯狂android讲义>. QuickContactBadge继承了ImageView,因此它的本质也是图片,也可以通过android:src属性指定它显示的图片.Qu ...

  2. threejs 鼠标移动控制模型旋转

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  3. Spark SQL源码剖析(一)SQL解析框架Catalyst流程概述

    Spark SQL模块,主要就是处理跟SQL解析相关的一些内容,说得更通俗点就是怎么把一个SQL语句解析成Dataframe或者说RDD的任务.以Spark 2.4.3为例,Spark SQL这个大模 ...

  4. Matlab学习-(4)

    1. 函数 1.1 原始方法 之前我调用函数的方法是,首先写好函数文件,然后保存,然后在主函数中调用.这种方法的不足在于会导致你的工作目录的文件太多,从而导致很乱.在网上找了一些解决方法. 1.2 本 ...

  5. 从零开始学AB测试:躲坑篇

    AB测试的原理很简单,只用到了最简单的统计假设检验,但表面的简单通常都隐藏着陷阱,这一点没有经过实践的摸爬滚打是不容易看到的,今天我就把前人已经踩过的坑,一共15个,给大家分享一下.在分享之前,大家脑 ...

  6. 分析PE

    PE文件是Windows平台下可执行文件标准格式,浓缩了微软工程师的设计精华,历经40年依旧保持着原有的设计.分析PE文件对于研究Windows操作系统有着重要的实践意义,对于逆向分析有着重要的指导作 ...

  7. 2层感知机(神经网络)实现非线性回归(非线性拟合)【pytorch】

    import torch import numpy import random from torch.autograd import Variable import torch.nn.function ...

  8. AWR发现TOP Event log file sequential read

    对客户DB进行巡检,发现TOP EVENT是LOG FILE Sequential read 等待事件说明 https://www.xuebuyuan.com/zh-hant/1743045.html ...

  9. tp5--路由的使用方法(深入)

    懒得写注释,直接上代码 配置文件Route: <?php use think\Route; //tp5路由测试 //动态注册 //Route::rule('路由表达式','路由地址','请求类型 ...

  10. 当git上只做文件大小写重命名的修改时,如何躲坑

    一. 提交时 假设修改ABC.java为Abc.java. 1.1 如果使用git命令进行仅涉及大小写的重命名 1.1.1 设置git库为大小写敏感(不建议) $ git config core.ig ...