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. 中国剩余定理(CRT)

    只看懂了CRT,EXCRT待补.... 心得:记不得这是第几次翻CRT了,每次都有迷迷糊糊的.. 中国剩余定理用来求解类似这样的方程组: 求解的过程中用到了同余方程. x=a1( mod x1) x= ...

  2. Pet BFS

    一天早上小明醒来时发现他的宠物仓鼠不见了. 他在房间寻找但是没找到仓鼠. 他想用奶酪诱饵去找回仓鼠. 他把奶酪诱饵放在房间并且等待了好几天. 但是可怜的小明除了老鼠和蟑螂没见到任何东西. 他找到学校的 ...

  3. 利用Putty建立SSH的tunnels访问内网资源

    适用场景访问阿里或者腾讯云只针对内网开放的资源. 本文以SQLSERVER 举例 举例你的内网 SQLSERVER的访问地址是192.168.33.88 . 你的Microsoft SQL Serve ...

  4. webform repeater 的使用

    1  repeater    定义: 重复器    根据数据库里的内容将repeater里的内容重复赋值 ,在itemtemplate下   配合<%# Eval(" ") ...

  5. 关于赋值的Java面试题

    面试题:(1) short s = 1:s = s + 1;(2) short s = 1;s += 1;问:上面两个代码有没有问题,如果有,哪里有问题? 答:(1) 第一个是错的,会报错损失精度,因 ...

  6. TensorFlow keras vgg16net的使用

    from tensorflow.python.keras.applications.vgg16 import VGG16,preprocess_input,decode_predictions fro ...

  7. java 多线--静态代理模式

    我们使用 java 多线程时,都需要通过线程代理对象来启动线程,常见的写法: new Thread(target).start(); 这在设计模式中叫静态代理模式,静态代理模式组成; 1.公共接口 2 ...

  8. Caused by:java.lang.ClassNotFoundException:org.apache.hadoop.yarn.util.Apps

    错误原因 缺少hadoop-yarn.jar包. 导入jar包就好了~-~

  9. 13206抢票代码 py

    抢票代码 https://github.com/Bingshuli/12306Python 谷歌驱动 http://chromedriver.storage.googleapis.com/index. ...

  10. 点击 QTableView,触发事件

    Here is an example of how you can get a table cell's text when clicking on it. Suppose a QTableView ...