SpringBoot 中简单使用JPA

SpringBoot整合JPA

1、什么是JPA

JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。——百度百科
通俗的来说,就是我们只需要在项目中继承JPA的接口,在配置文件中选择实现JPA标准的框架(Hibernate、TopLink、JDO),JPA就可以帮我们完成大部分的增删改查的功能,省去了编写DAO层的步骤。

2、JPA基于注解的使用

注解 功能
@Entity 声明类为实体或表。
@Table 声明表名。
@Basic 指定非约束明确的各个字段。
@Embedded 指定类或它的值是一个可嵌入的类的实例的实体的属性。
@Id 指定的类的属性,用于识别(一个表中的主键)。
@GeneratedValue 指定如何标识属性可以被初始化,例如自动、手动、或从序列表中获得的值。
@Transient 指定的属性,它是不持久的,即:该值永远不会存储在数据库中。
@SequenceGenerator 指定持久属性栏属性。
@TableGenerator 指定在@GeneratedValue注解中指定的属性的值。它创建了一个序列。
@AccessType 指定在@GeneratedValue批注指定属性的值发生器。它创造了的值生成的表。
@JoinColumn 这种类型的注释用于设置访问类型。如果设置@AccessType(FIELD),则可以直接访问变量并且不需要getter和setter,但必须为public。如果设置@AccessType(PROPERTY),通过getter和setter方法访问Entity的变量。
@UniqueConstraint 指定一个实体组织或实体的集合。这是用在多对一和一对多关联。
@ColumnResult 指定的字段和用于主要或辅助表的唯一约束。
@ManyToMany 参考使用select子句的SQL查询中的列名。
@ManyToOne 定义了连接表之间的多对多一对多的关系。
@OneToMany 定义了连接表之间的多对一的关系。
@OneToOne 定义了连接表之间有一个一对一的关系。
@NamedQueries 指定命名查询的列表。
@NamedQuery 指定使用静态名称的查询。

3、项目实践

3.1、创建spring boot项目
在这里插入图片描述
在左侧点击SQL选项,选中JPA与MYSQL,再引入test的模块

创建完成的目录结构
在这里插入图片描述

3.2、pom文件中的相关依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.tianqicode</groupId>
    <artifactId>spring-boot-jpa</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-boot-jpa</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!-- JPA启动器依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <!-- web启动器依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- mysql依赖 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!-- 测试相关依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.4.RELEASE</version>
            <scope>compile</scope>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-test</artifactId>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

3.3、配置文件

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/how2java?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=admin
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.properties.hibernate.hbm2ddl.auto=update
spring.jpa.show-sql=true

jpa.hibernate.ddl-auto是hibernate的配置属性,其主要作用是:自动创建、更新、验证数据库表结构。该参数的几种配置如下:
·create:每次加载hibernate时都会删除上一次的生成的表,然后根据你的model类再重新来生成新表,哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。
·create-drop:每次加载hibernate时根据model类生成表,但是sessionFactory一关闭,表就自动删除。
·update:最常用的属性,第一次加载hibernate时根据model类会自动建立起表的结构(前提是先建立好数据库),以后加载hibernate时根据model类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等应用第一次运行起来后才会。
·validate:每次加载hibernate时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。
3.4、创建实体类

package com.tianqicode.testjpa.bean;

import javax.persistence.*;

@Entity
@Table(name = "category_")
public class Category {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private int id;

    @Column(name = "name")

    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Category{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

@Entity 注解表示这是个实体类
@Table(name = “category_”) 表示这个类对应的表名是 category_
@Id 表明主键
@GeneratedValue(strategy = GenerationType.IDENTITY) 表明自增长方式
@Column(name = “id”) 表明对应的数据库字段名

3.5、创建CategoryDAO

package com.tianqicode.testjpa.dao;

import org.springframework.data.jpa.repository.JpaRepository;

import com.tianqicode.testjpa.bean.Category;

public interface CategoryDAO extends JpaRepository<Category, Integer> {

}

3.6、创建CategoryController

package com.tianqicode.testjpa.controller;


import com.tianqicode.testjpa.bean.Category;
import com.tianqicode.testjpa.dao.CategoryDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;


import java.util.List;

@Controller
public class CategoryController {

    @Autowired
    CategoryDAO categoryDAO;

    @RequestMapping(value = "test")
    public List<Category> categoryList() {

        List<Category> cs = categoryDAO.findAll();

        return cs;
    }
}

3.7、编写测试类

package com.tianqicode.testjpa.controller;

import com.tianqicode.testjpa.SpringBootJpaApplication;
import com.tianqicode.testjpa.bean.Category;
import com.tianqicode.testjpa.service.CategoryService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;


import java.util.List;

@RunWith(SpringRunner.class)//使用spring环境运行,否则无法注入对象
@SpringBootTest(classes = SpringBootJpaApplication.class)

public class test {

    @Autowired
    CategoryService categoryService;

    @Test
    public void testJPA() {

        List<Category> cs = categoryService.findAll();

        for (Category category : cs) {
            System.out.println(category);

        }
    }
}

3.7、运行
在这里插入图片描述
控制台成功遍历输出了数组

同时也发现了日志中hibernate输出的日志:
在这里插入图片描述

4、JPA的条件查询

4.1、认识JPA的条件查询

JPA中其实准备了一部分的条件查询,例如findById。但是如果需要根据数据表中的外键进行查询,则需要我们自己为接口添加方法。
JPA在这里遵循Convention over configuration(约定大约配置)的原则,遵循spring 以及JPQL定义的方法命名。Spring提供了一套可以通过命名规则进行查询构建的机制。这套机制会把方法名首先过滤一些关键字,比如 find…By, read…By, query…By, count…By 和 get…By 。系统会根据关键字将命名解析成2个子语句,第一个 By 是区分这两个子语句的关键词。这个 By 之前的子语句是查询子语句(指明返回要查询的对象),后面的部分是条件子语句。如果直接就是 findBy… 返回的就是定义Respository时指定的领域对象集合,同时JPQL中也定义了丰富的关键字:and、or、Between等等
在这里插入图片描述

4.2、项目实践

数据库category
在这里插入图片描述
数据库Product_
在这里插入图片描述
这里Product表的外键是cid,这里没有在MySQL中设置外键,而是在代码中进行约束
Product实体类

package com.tianqicode.testjpa.bean;

import javax.persistence.*;

@Entity
@Table(name = "product_")
public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private int id;

    @Column(name = "name")
    private String name;

    @Column(name = "price")
    private float price;

    @ManyToOne//多对一约束
    @JoinColumn(name = "cid")//声明外键所在的列
    private Category category;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public float getPrice() {
        return price;
    }

    public void setPrice(float price) {
        this.price = price;
    }

    public Category getCategory() {
        return category;
    }

    public void setCategory(Category category) {
        this.category = category;
    }

    @Override
    public String toString() {
        return "Product{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", price=" + price +
                ", category=" + category +
                '}';
    }
}

DAO接口

package com.tianqicode.testjpa.dao;

import com.tianqicode.testjpa.bean.Category;
import com.tianqicode.testjpa.bean.Product;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface ProductDAO extends JpaRepository<Product, Integer> {

    List<Product> findByCategory(Category category);
}

方法的命名要遵循驼峰命名的规则,且所有关键词区分大小写,在方法中传入需要的对象参数

Controller类

package com.tianqicode.testjpa.controller;

import com.tianqicode.testjpa.bean.Category;
import com.tianqicode.testjpa.bean.Product;
import com.tianqicode.testjpa.dao.ProductDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import java.util.List;

@Controller
public class ProductController {

    @Autowired
    ProductDAO productDAO;

    public List<Product> findAll() {

        List<Product> ps = productDAO.findAll();

        return ps;
    }

    public List<Product> findByCategory(Category category) {

        List<Product> ps = productDAO.findByCategory(category);

        return ps;
    }
}

测试类

@Test
    public void testProductFindByCategory() {

        Category category = new Category();

        category.setId(4);

        List<Product> ps = productController.findByCategory(category);

        for (Product product : ps) {
            System.out.println(product);
        }

运行

在这里插入图片描述

条件查询成功。

发布了30 篇原创文章 · 获赞 2 · 访问量 614

猜你喜欢

转载自blog.csdn.net/qq_43585377/article/details/104619923