JPA概述、Spring Boot + JPA的应用

本文介绍了JPA作为Java持久化API的规范,对比了JPA与Hibernate、Mybatis的区别,并详细阐述了JPA的优势和实现,包括JPA在Spring Boot中的应用步骤。总结了JPA作为ORM框架的标准化、简单易用和面向对象的查询能力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JPA概述

JDBC

是一个类一个接口,定义了访问数据库的通用接口,可以用java规范的访问数据库,

持久层框架

数据的存储,也就是三层框架中的Dao层,

Hibernate:开源的轻量级的ORM

  • ORM(Object Relation Mapping):对象(内存中的java对象)关系(表的数据)映射(Mapping映射)
    • 由面向对象的开发方法而产生的,对象和关系数据库
    • 对象和关系数据是业务实体的两种表现形式
    • ORM实现内存中对象到关系数据库数据的映射,以对象管理表
  • 将对象映射到数据库中存储的表,操作对象就是操作数据库中的表

Mybatis:半ORM

  • sql语句需要手工编写
  • 支持定制化sql,存储过程以及高级映射
  • 两种方式进行持久化的处理:xml或注解来配置映射原生信息

总结:

  • Hibernate自动化,Mybatis手工编写sql
  • 对于复杂的程序推荐Mybatis,因为Mybatis灵活,可以特定的数据库的sql语句,但是Mybatis移植性不好,因为编写的sql语句只适应一个数据库,
  • 相比之下Hibernate较好,在不修改代码的情况下就可以使用不同的数据库

如果项目需要适配不同的数据库,使用Hibernate

如果是互联网应用,用大量的sql语句,需要随时优化建议使用Mybatis

JPA是什么

sun公司定义的一个规范

JPA(Java Persistence API):java持久API(用来对象持久化的)也就是操作数据库的

用来在java对象和关系数据库之间保存数据,充当面向对象的领域模型和关系数据库系统之间的桥梁

JPA定义了一些通用的接口,通过接口可以可以访问不同的数据库。

JPA使用有两种方式,一种是JDK注解,一种是XML文件描述对象关系表的映射关系,并将运行期的实体对象持久化到数据库中

Sun引入JPA ORM规范原因

  • 简化Java EE 和Java SE 应用开发工作
  • Sun希望整合ORM技术,实现天下归一

总结:

JPA等同于JDBC的规范,通过JPA可以集成对数据库的统一访问

JPA的实现

规范就是一个文档就是一个说明,规范不能直接的使用,我们要使用JPA规范的实现

  • Hibernate
    • JPA的始作俑者就是Hibernate的作者
    • Hibernate 从3.2开始兼容JPA
  • OpenJPA
    • OpenJPA是Apache 组织提供的开源项目
  • EclipseLink
    • EclipseLink的前身是Toplink,Oracle的企业级ORM.

JPA的优势

  • 标准化
    • 可以使用JPA访问不同的数据库,不同的ORM框架,只要少量的修改代码或者是不修改代码
  • 简单易用,继承了不同的框架:
    • JPA提供简单的统一编程模型,可以在Spring,SpringBoot框架中使用
  • 可媲美JDBC的查询能力:
    • JPA是面向对象的以对象的方式来访问表中的数据
    • 定义了独特的JPQL语言
  • 支持面向对象的高级特性
    • 类之间的继承,多态,类和类之间的复杂关系

总结:标准化是最大的优势

JPA的三方面技术

ORM映射元数据:

  • 支持XML和注解两种元数据形式,元数据描述对象和表之间的映射关系,框架将对象持久化到数据库表中

JPA和API

  • 对java对象执行CRUD行为,框架会把你的方法转换成数据库能识别的sql语句

查询语言(JPQL)

  • 数据能存进去还得能查出来,通过JPQL可以获取持久层中的数据,因为使用的是JPQL是面向对象的,不是面向数据库的,即使你更换了数据库软件,也不用修改程序

JPA和Hibernate

  • jpa是Hibernate的抽象,jpa就相当于接口,Hibernate就相当于接口的实现
  • Hibernate本身就是ORM框架,可以独立使用去访问数据库,而且还扩展了其他的功能
  • JPA是Hibernate功能的一个子集

总结:JPA是规范,Hibernate是JPA的具体实现,Hibernate的实现超过了JPA,还实现了一些扩展功能

JPA和Mybatis

Mybatis是一个独立的框架不算真正的ORM,和JPA规范没有关系,

jpa是对象与表之间的映射

Mybatis是对象和结果集的映射

总结:JPA是面向对象的,Mybatis是面向SQL

总结

JPA:是一个规范,制定访问数据库的API(接口和类)

使用JPA以标准的方式访问数据库

JPA的实现:

  • Hibernate
  • OpenJPA
  • EclipseLink

JavaApplication----调用JPA中的接口-----》实现Hibernate-----》访问数据库

JPA的应用

使用JPA的主要步骤:

  • 新建persistence.xml,文件名称是固定的,放在类路径的META-INF目录(目录和文件名称都是固定的)
    • 创建jpa的单元,一个单元指定一个数据库的相关信息
    • 配置数据库的相关属性,连接到指定的数据库
    • 指定JPA的实现提供者(Hibernate,openJPA):只有一个实现的话,默认是可以不写的。
    • 指定实体类的信息。
  • 创建实体类,使用注解或者xml配置文件,描述实体类和数据库表的关系(定义元数据信息)
  • 在java的应用中使用JPA的API实现对数据的crud.
    • 主要对象EntityManagerFactory, EntityManager,EntityTransaction

开发环境的准备:

  • 使用mysql数据库
  • 使用的ide: idea
  • 使用springboot+jpa依赖

JPA项目的开发步骤

  • 新建Spring boot maven项目
  • 加入JPA的实现jar ,加入的HIibernate -5.3.2/ required/ *.jar,或者加入依赖

(2条消息) Hibernate release(distribution)包下载!_donghaixiaoni的博客-优快云博客

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--引入mysql的驱动: -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.45</version>
</dependency>
  • 在resources/application.properties
#配置数据库连接信息
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/jpa
spring.datasource.username=root
spring.datasource.password=x5

#jpa的和相关配置;
#开发阶段可以没置为true,开启了逆向工程:在实际上线运行阶段,实体类和底层的数据库表都是已经存在的,应该是f
# 毅管库和java碰向工程正同王程:
# 逆同王程:存在数婚库的表,然后经韶库表可以生成支实体类;
# 正网工程:兹存在变体类,然后根帮实体类。生成底层的表。
spring.jpa.generate-ddl=true

#create :没置为create,每次运行程序都会将惊来的数貂表丽除,然后重新创述一个表
#create-drop :没次将创建一个数据衣,数姻表使用完毕之后,将数据表再次删除。
#none将动糖不生效
#update如果你没定的实体类发生了改变,数据表会更新﹔
#如果当前数据库当中有数据表,就使用原来的表。没有数据表,就会创建一个数据表。也是在开发当中经常使用的属性
#validate实体类和数瘩表进行校验,如果属性或者个数不一致,就会抛出异常。
spring.jpa.hibernate.ddl-auto=update

#操作实体对象的时候,会生成sqL语句:false不生成sqL语每:
spring.jpa.show-sql=true

#指定了数据库的版本
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
  • 创建实体类,在类中使用JPA有关的注解,声明元数据的信息。指定实体类的属性和数据库表的列的关系。
package com.example.demo.domain;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

/***
 * 宠物实体类
 * @author Administrator
 */
//@Entity 描述实体了和表之间的关系,name表示表的名字
@Entity(name="t_pet")
public class Pet {

    @Id //表示该属性对应数据库的逐渐列,而且自增
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id;
    @Column
    private String color;
    @Column
    private String pname;

    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getColor() {
        return color;
    }
    public void setColor(String color) {
        this.color = color;
    }
    public String getPname() {
        return pname;
    }
    public void setPname(String pname) {
        this.pname = pname;
    }

    @Override
    public String toString() {
        return "Pet{" +
                "id=" + id +
                ", color='" + color + '\'' +
                ", pname='" + pname + '\'' +
                '}';
    }
}
  • 创建测试类
package com.example.demo;

import com.example.demo.dao.PetDao;
import com.example.demo.domain.Pet;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;

import java.util.List;
import java.util.Optional;

@SpringBootTest(classes = DemoApplication.class)
class DemoApplicationTests {

    @Test
    void contextLoads() {
        System.out.println("-----------初始化数据库-----------");
    }

    @Autowired
    PetDao petDao;


    @Test
    void addPet(){
        System.out.println("add");
        Pet pet = new Pet();
        //pet.setId();
        pet.setPname("Tom");
        pet.setColor("blue");
        petDao.save(pet);
    }

    @Test
    void addPet1(){
        System.out.println("add");
        Pet pet = new Pet();
        //pet.setId();
        pet.setPname("jierui");
        pet.setColor("zong");
        petDao.save(pet);
    }

    /***
     * 更新宠物信息
     * save(obj)
     *       如果id是null,执行insert操作
     *   如果id不是null,查询数据库
     *        id在数据库存在   执行update
     *        id在数据不存在   执行insert
     */
    @Test
    public void updatePet() {
        //创建Pet对象
        Pet pet=new Pet();
        pet.setId(2);
        pet.setPname("小黑");
        pet.setColor("黄黑");
        petDao.save(pet);
    }


    //根据id查询
    /**
     * 查询操作:findByid(); JpaRepository接口当中提供的L:不是我们自定义
     * 查询的内容封装到了 optional对象:
     * get();方法获得Pet对象。啊如果查询的对象存在,返回的是一个异常
     * NosuchElementException
     */
    @Test
    void find(){
        //获得一个Optional对象
        Optional<Pet> optional = petDao.findById(1);
        Pet pet = optional.get();
        System.out.println(pet.getId()+" "+pet.getPname()+" "+pet.getColor());
    }

    /**
     * 返回的一个列表集合
     */
    @Test
    void findAllPets(){
        //获得一个Optional对象
        List<Pet> list = petDao.findAll();
        for (Pet pet: list) {
            System.out.println(pet.getId()+" "+pet.getPname()+" "+pet.getColor());
        }
    }

    /**
     * 查询:返回的是列表集合
     * findAll();没有指定任何的参数,查询的列老
     * findAll();在使用时可以指定参数,Sort象,指定排序字段.
     */
    @Test
    void findAllPets1(){
        //获得一个Optional对象
        Sort sort = Sort.by(Sort.Direction.DESC,"pname");
        List<Pet> pname = petDao.findAll(sort);
        for (Pet pet : pname) {
            System.out.println(pet.getPname());
        }
    }

    /**
     * 分页查询
     * pageable :接口类型:
     * pageRequest :接口的实现类对象:实现类不是直接new,构造器protect
     *      PageRequest:类当中提供了of方法,返回本类对象:
     *      of();方法,static静态方法:
     *      参数一:
     *      page:查询第一页,用户指定; 0代表第一页
     *      size:当前页显示的记录数
     *      Direction.AsC指定升序排序: Direction.DESC指定的降序排序
     *      properties:指定具体的哪个属性进行排序
     */
    @Test
    void findAllPetsWithPage(){
        //封装了一些分页的参数
        PageRequest pageable = PageRequest.of(0, 2,Direction.DESC,"id");
        Page<Pet> pe = petDao.findAll(pageable);
        int totalPages = pe.getTotalPages();
        long totalElements = pe.getTotalElements();

        System.out.println("totalPages="+totalPages);
        System.out.println("totalElements="+totalElements);

        //获取分页查询到的数据集合
        List<Pet> list = pe.getContent();
        for(Pet pet:list) {
            System.out.println(pet.getId()+"\t"+pet.getPname()+"\t"+pet.getColor());
        }
    }

    /**
     * 传递的是对象
     */
    @Test
    void delPet(){
        Pet pet = new Pet();
        pet.setId(2);
        petDao.delete(pet);
    }

    @Test
    public void delByName(){
        List<Pet> list = petDao.findByPname("Tom");
        System.out.println(list);

        //根据color查询
        List<Pet> list1 = petDao.findByColor("blue");
        System.out.println(list1);

        //联合查询: 根据pname和color联合查询:
        List<Pet> list2
                = petDao.findByPnameAndColor("小黑", "黄黑");
        System.out.println(list2);

        //根据id区间查询,并且排序:
        List<Pet> list3 = petDao.findByIdBetweenOrderById(1, 5);
        System.out.println(list3);
    }
}
  • 自定义查询
package com.example.demo.dao;

import com.example.demo.domain.Pet;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

/**
 *创建PetDao接口,实现pet实体类的操作:
 * JpaRepository <t, ID> jpa提供的一个接口:接口的当中定义了实体的基本操作
 * T指定具体操作的实现类:Pet实体类
 * ID指定主键字段的类型(实体类当中带有id注解的属性)Integer
 */
public interface PetDao extends JpaRepository<Pet,Integer> {

    /**
     * 方法定义注意事项:
     * 方法的返回值是根据实际的业务需求定义:List pet
     * 方法的名称必须满足规范:findByXxxfindBy固定开始xxx属性名称: findByPname
     * 在测试类中直接编写
     * @param pname
     * @return
     */
    List<Pet> findByPname(String pname);

    List<Pet> findByColor(String color);


    /*
       根据pname查询并且根据color查
       select * from t_pet pet0_ where pet0_.color=? and pet0_panme =?
     */
    List<Pet> findByPnameAndColor(String pname,String color);


    /**
     * 根据id 查询 : 查询id在 1-5之间的pet对象:
     */
    List<Pet> findByIdBetweenOrderById(Integer minId, Integer maxId);


}
  • 运行结果:在控制台进行查看
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值