Javaweb——Spring Boot 系列(10)以JPA方式操作Oracle-XE-11g

一、数据库工作准备

  • 在上一篇中,已经成功启动 Docker,并且启动 Oracle-xe-11g 作为一个容器运行,同时也在 Navicat 成功连接上 Oracle 数据库。
  • 为了 Java 程序能够正确交互数据库,需要在数据库中做一些准备,主要有两个工作:准备 Hibernate 需要的一个序列和主键自增所需的触发器以及相关的用户。

1、创建用户和用户赋权

  • 新建一个用户,命名为 boot,密码也设置为 boot
    create user boot identified by boot;
    
  • 创建用户后,得赋予创建会话等权限,不然无法登录
    grant create session,resource to boot;
    

2、准备序列

  • 使用 Spring Boot 以 JPA 方式操作数据库,往往会结合 Hibernate 进行,而在这里使用 Hibernate 自动将实体类映射为数据表格时,会用到一个序列hibernate_sequence,因此先要把这个序列准备好。
  • 在 Navicat 软件中,展开 Oracle 服务器节点,选中目标数据库,右键新建查询,在查询脚本编辑界面中,编辑如下 sql 语句:
    create sequence hibernate_sequence increment by 1 start with 0 nomaxvalue nocache
    

3、实现主键自增

  • 在一个数据表中,通常会选择一个 ID 列作为主键,并且让该字段是自增的,Oracle 数据库不像 MySQL 那样有支持标识符自增的功能,需要通过编写前触发器来实现。
  • sql 语句如下:
    create or replace trigger ID_autoincrement
    before insert on PERSON for each row
    when(new.id is null)
    begin
    select hibernate_sequence.nextval into :new.id from dual;
    end;
    
  • 这里的 PERSON 就是目标数据表。

二、项目代码编辑

  • 接下来开始编辑项目的代码。

1、创建项目和准备依赖

  • 首先,在 IDEA 中使用项目创建向导新建一个 Spring Boot 项目,用 Spring Initializer 并勾选 web 和 JPA 依赖。
  • 项目信息如下:
    <groupId>com.pyc</groupId>
    <artifactId>springjpa</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>springjpa</name>
    
  • 这里要操作的数据库是 Oracle 数据库,因此需要 Oracle 数据库的驱动包:ojdbc6.jar,但是这个包在 Maven 中央库中没有,因此我们需要手动下载后进行打包到本地 Maven 库;打包的命令如下(在 CMD 窗口)
    mvn install:install-file -DgroupId=com.oracle "-DartifactId=ojdbc6" "-Dversion=11.2.0.2.0" "Dfile=ojdbc6.jar 下载存放的路径"
    
  • 打包成功后,在项目的 POM 文件中加入 ojdbc6.jar 的坐标:
    <!--        Oracle 数据库依赖-->
        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc6</artifactId>
            <version>11.2.0.2.0</version>
        </dependency>
    
  • 同时增加 Google guava 依赖,该依赖可以提供大量的 Java 工具类。
    <!--        Google guava 依赖-->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>18.0</version>
        </dependency>
    
  • 整个 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>1.3.0.M1</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.pyc</groupId>
        <artifactId>springjpa</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>jar</packaging>
        <name>springjpa</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
    <!--        Oracle 数据库依赖-->
            <dependency>
                <groupId>com.oracle</groupId>
                <artifactId>ojdbc6</artifactId>
                <version>11.2.0.2.0</version>
            </dependency>
    <!--        Google guava 依赖-->
            <dependency>
                <groupId>com.google.guava</groupId>
                <artifactId>guava</artifactId>
                <version>18.0</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jpa</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</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>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    

2、准备一个初始数据表的 SQL 文件

  • 在 src/main/resources 目录下,新建一个 data.sql 文件,编辑如下代码:
    insert into person(id,name,age,address) values(hibernate_sequence.nextval,'pyc',22,'汕尾');
    insert into person(id,name,age,address) values(hibernate_sequence.nextval,'xx',21,'天津');
    insert into person(id,name,age,address) values(hibernate_squence.nextval,'yy',20,'上海');
    insert into person(id,name,age,address) values(hibernate_sequence.nextval,'zz',24,'大理');
    insert into person(id,name,age,address) values(hibernate_sequence.nextval,'aa',25,'北京');
    insert into person(id,name,age,address) values(hibernate_sequence.nextval,'bb',26,'南昌');
    
  • 该文件在项目第一次运行成功后请删除或者更改文件名后缀

3、编辑 Properties 文件

  • 编辑 application/properties 文件配置数据源、JPA 和 log 的相关属性。
    # 配置数据源
    spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
    spring.datasource.url=jdbc\:oracle\:thin\:@localhost\:1521\:XE
    spring.datasource.username=boot
    spring.datasource.password=boot
    # 利用 Hibernate 自动维护数据库表结构的功能
    spring.jpa.hibernate.ddl-auto=update
    # 设置 Hibernate 操作数据库的时候在控制台显示真实的 spl 语句
    spring.jpa.show-sql=true
    # 让控制器输出 json 字符串格式更美观
    spring.jackson.serialization.indent-output=true
    logging.file=log.log
    logging.level.org.springframework.web=DEBUG
    

4、实体类

  • 创建一个类名为 Person 的实体类,代码如下:
    package com.pyc.springjpa.domain;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.NamedQuery;
    
    @Entity //指明这是一个和数据库表映射的实体类
    @NamedQuery(name = "Person.withNameAndAddressNamedQuery",
            query = "select p from Person p where p.name=?1 and p.address=?2")
    public class Person {
        @Id     // 指明这个属性映射为数据库的主键
        @GeneratedValue     //指明主键的生成方式为自增
        private Long id;
        private String name;
        private Integer age;
        private String address;
    
        public Person() {
            super();
        }
    
        public Person(Long id, String name, Integer age, String address){
            super();
            this.address=address;
            this.name=name;
            this.age=age;
            this.id=id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        public Long getId() {
            return id;
        }
    
        public String getName() {
            return name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public String getAddress() {
            return address;
        }
    }
    
  • Hibernate 会自动根据属性名生成数据表的字段名。

5、接口编写

  • 创建一个接口类,编写用于访问数据库数据的接口方法,代码如下:
    package com.pyc.springjpa.dao;
    
    import com.pyc.springjpa.domain.Person;
    import org.springframework.data.repository.query.Param;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.data.jpa.repository.Query;
    
    import java.util.List;
    
    public interface PersonRepository extends JpaRepository<Person,Long> {
        // 根据地址查询,返回值为列表
        List<Person> findByAddress(String address);
        // 根据姓名和地址查询,返回值为单个对象
        Person findByNameAndAddress(String name, String address);
        // 使用 @Query 查询,参数按照名称绑定
        @Query("select p from Person p where p.name= :name and p.address= :address")
        Person withNameAndAddressQuery(@Param("name")String name,@Param("address")String address);
        //使用 @NamedQuery 查询,在实体类中已注解
        Person withNameAndAddressNamedQuery(String name, String address);
    
    }
    

6、Controller

  • 编写一个控制器,用于控制前台对接口的调用逻辑,代码如下:
    package com.pyc.springjpa.web;
    
    
    import com.pyc.springjpa.dao.PersonRepository;
    import com.pyc.springjpa.domain.Person;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.PageRequest;
    import org.springframework.data.domain.Sort;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.util.List;
    
    @RestController
    public class DataController {
        // Spring Data JPA 已自动注册bean,因此可以自动注入
        @Autowired
        PersonRepository personRepository;
        /*
         *  保存
         *  save 支持批量保存:<S extends T> Iterable<S> save(Iterable<S> entities);
         *  删除
         *  支持使用 id 删除对象、批量删除以及删除全部
         *  void delete(ID id)
         *  void delete(T entity)
         *  void delete(Iterable<? extends T>entities);
         *  void deleteAll();
         */
        @RequestMapping("/save")
        public Person save(String name,String address,Integer age){
            Person p;
            p = personRepository.save(new Person(null, name,age,address));
            return p;
        }
        /*
         * 测试 findByAddress
         */
        @RequestMapping("/q1")
        public List<Person> q1(String address){
            List<Person> people;
            people = personRepository.findByAddress(address);
            return people;
        }
        // 测试 findByNameAndAddress
        @RequestMapping("/q2")
        public Person q2(String name, String address){
            Person person;
            person = personRepository.findByNameAndAddress(name,address);
            return person;
        }
        //测试 withNameAndAddressQuery
        @RequestMapping("/q3")
        public Person q3(String name, String address){
            Person p;
            p = personRepository.withNameAndAddressQuery(name, address);
            return p;
        }
        //测试 withNameAndAddressNamedQuery
        @RequestMapping("/q4")
        public Person q4(String name, String address){
            Person p;
            p = personRepository.withNameAndAddressNamedQuery(name, address);
            return p;
        }
        //排序
        @RequestMapping("/sort")
        public List<Person> sort(){
            List<Person> people;
            people = personRepository.findAll(new Sort(Sort.Direction.ASC, "age"));
            return people;
        }
        // 测试分页
        @RequestMapping("/page")
        public Page<Person> page(){
            Page<Person> pagePeople;
            pagePeople = personRepository.findAll(new PageRequest(1,2));
            return pagePeople;
        }
    }
    

三、项目运行测试

  • 在入口类中启动运行,控制台若无错误,到 Navicat 中展开 boot 数据库,可以看到生成了一个名为 PERSON 的数据表
    在这里插入图片描述
  • 在浏览器中访问 localhost:8080/save?name=csdn&address=杭州&age=20,后台返回 JSON 格式的数据,浏览器页面如下:
    在这里插入图片描述
  • 回到 Navicat,打开 PERSON 数据表,数据如下:
    在这里插入图片描述
  • 浏览器访问 localhost:8080/q1?address=上海
    在这里插入图片描述
  • 浏览器访问 localhost:8080/q2?address=上海&name=pyc
    在这里插入图片描述
  • localhost:8080/q3?address=汕尾&namepyc
    在这里插入图片描述
  • localhost:8080/q4?address=大理&name=zz
    在这里插入图片描述
  • localhost:8080/sort
    在这里插入图片描述
  • localhost:8080/page
    在这里插入图片描述

上一篇
下一篇

发布了148 篇原创文章 · 获赞 15 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_42896653/article/details/104231609