JPA与hibernate——-JPA01

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接口,但详细实现则由服务厂商来提供实现。           

OSI七层模子

JPA与hibernate-------JPA01

 

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的设置文件

 

JPA与hibernate-------JPA01

 

 

 

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

    }
}

 

原创文章,作者:admin,如若转载,请注明出处:https://www.2lxm.com/archives/8575.html