74、SpringBoot 整合 Spring Data JDBC

news2024/11/24 19:28:56

总结:用起来跟 Spring Data JPA 差不多

什么是 JdbcTemplate?(Template译为模板)
Spring 框架对 JDBC 进行封装,使用 JdbcTemplate 方便实现对数据库操作

★ Spring Data JDBC

既不需要JPA、Hibernate这种ORM框架,但Spring Data还是提供了面向对象的封装。

——它相当于是一种轻量化的持久化技术,用起来比Spring JDBC更方便,
   但又不像Spring Data JPA那么需要大量注解、复杂

它相当于是一个折中。

★ Spring Data JDBC的功能

大致包括如下几方面功能:
- DAO接口只需继承CrudRepository或PagingAndSortingRepository,
  Spring Data JDBC能为DAO组件生成实现类、类似于Spring Data JPA。
- Spring Data JDBC支持方法名关键字查询、类似于Spring Data JPA
- Spring Data JDBC支持用@Query定义查询语句。
- Spring Data JDBC同样支持DAO组件添加自定义的查询方法
                  ——————通过添加额外的父接口,并为额外的该接口提供实现类,
                        Spring Data JDBC就能该实现类中的方法“移植”到DAO组件中。
- 一般不支持样本查询;也不支持Specification查询。

★ Spring Data JDBC VS Spring Data JPA

Spring Data JDBC相当于“轻量化”的Spring Data JPA。
Spring Data JDBC的功能不如Spring Data JPA强大(毕竟它底层没有ORM框架的加持)。
Spring Data JDBC也不需要处理复杂的ORM映射、实体对象的生命周期管理等,
因此Spring Data JDBC用起来更简单。 
——Spring Data JDBC有点类似MyBatis

★ Spring Data JDBC映射规则

Spring Data JDBC默认的处理方式是“约定优于配置”的同名映射:

- 程序操作User对象,Spring Data JDBC对应于操作user表。
- 对于id数据列,自动被映射到对象的id属性。

▲Spring Data JDBC的注解:

- @Table:映射自定义的表名。非JPA注解
- @Column:映射自定义的列名,非JPA注解
- @Id:修饰标识属性,非JPA注解
- @PersistenceConstructor:修饰主构造器。当你的映射类中有多个构造器时,
                           你希望Spring Data JDBC用哪个构造器来创建对象,
                           就用该注解来修饰该构造器。

★ Spring Data JDBC操作数据库方法:

A. 全自动:方法名关键字查询。

B. 半自动:@Query指定查询语句。

C. 全手动:自己定义查询方法,即可用DataSource,也用JdbcTemplate。

★ Spring Data JDBC的编程步骤:

(1)定义映射类,为Java类添加@Table、@Column、@Id和 @PersistenceConstructor

(2)让DAO接口继承CrudRepository或PagingAndSortingRepository。

(3)在DAO接口中定义方法名关键字查询、@Query查询、完全自定义查询(需要额外的接口和实现类)

代码演示

其实跟 JPA 差不多

User 类

在这里插入图片描述

UserDao接口,

根据方法名关键字查询---------全自动,不用自己写sql的
也有通过注解 @Query 进行查询的 —>自己定义查询语句-----半自动,可以自己写sql语句
在这里插入图片描述

也可以自定义Dao接口,用来自己写sql和封装数据
在这里插入图片描述

自定义接口和实现类,来实现数据的查询,
一个基于 DataSource , 一个基于 jdbcTemplate
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

UserDaoTest 测试

测试类
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

application.properties

在这里插入图片描述

pom.xml

一个是 spring data jdbc 的依赖 , 一个是 mysql 的依赖,
创建项目的时候这个 mysql 的依赖老是不完整,所以要记录下
在这里插入图片描述

完整代码

User

package cn.ljh.app.domain;

import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.PersistenceConstructor;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table;

/**
 * author JH
 */


@Data
//此处不能添加JPA注解,因为此项目没有用到 JPA
@Table("user_inf")
public class User
{

    @Column(value = "user_id")
    @Id
    private Integer id;
    private String name;
    private String password;
    private int age;

    /**
     * @PersistenceConstructor
     *  修饰主构造器。当你的映射类中有多个构造器时,
     *  你希望Spring Data JDBC用哪个构造器来创建对象,就用该注解来修饰该构造器
     */
    @PersistenceConstructor
    public User()
    {
    }

    public User(Integer id, String name, String password, int age)
    {
        this.id = id;
        this.name = name;
        this.password = password;
        this.age = age;
    }

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

UserDao

package cn.ljh.app.dao;


import cn.ljh.app.domain.User;
import org.springframework.data.jdbc.repository.query.Modifying;
import org.springframework.data.jdbc.repository.query.Query;
import org.springframework.data.repository.CrudRepository;

import java.util.List;


public interface UserDao extends CrudRepository<User,Integer>,CustomUserDao
{
    // 继承 CrudRepository 接口后,就已经有通用的 CRUD 操作,无需自己来书写这些方法
    //方法名关键字查询---------全自动

    //根据名字模糊查询
    List<User> findByNameLike(String namePattern);
    //根据年龄大小进行范围查询
    List<User> findByAgeGreaterThan(int startAge);

    List<User> findByAgeLessThan(int age);

    //根据年龄区间进行范围查询
    List<User> findByAgeBetween(int startAge , int endAge);

    //@Query 查询 --->自己定义查询语句-----半自动
    //rowMapperClass 或 rowMapperRef 是用来做自定义映射,查询出来的User对象的数据,映射到Student对象的属性上面去都可以,因为是自定义的。

    //根据密码模糊查询
    @Query("select * from user_inf where password like :passwordPattern")
    List<User> findBySql(String passwordPattern);

    //根据年龄范围修改名字
    @Query("update user_inf set name = :name where age between :startAge and :endAge")
    @Modifying //更改数据库数据需要用到这个注解
    int updateNameByAge(String name , int startAge , int endAge);

}

CustomUserDao

package cn.ljh.app.dao;

import cn.ljh.app.domain.User;

import java.util.List;

/**
 * author JH
 */
//自己定义的接口,用来实现全手动的查询
public interface CustomUserDao
{
    //通过名字进行模糊查询,使用 dataSource
    List<User> customQueryUsingConnection(String namePattern);

    //通过名字进行模糊查询,使用 jdbcTemplate
    List<User> customQueryUsingTemplate(String namePattern);
}

CustomUserDaoImpl

package cn.ljh.app.dao.impl;

import cn.ljh.app.dao.CustomUserDao;
import cn.ljh.app.domain.User;
import lombok.SneakyThrows;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;
import java.sql.Array;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

/**
 * author JH
 */
public class CustomUserDaoImpl implements CustomUserDao
{
    private DataSource dataSource;
    private JdbcTemplate jdbcTemplate;

    //通过有参构造器进行依赖注入
    public CustomUserDaoImpl(DataSource dataSource, JdbcTemplate jdbcTemplate)
    {
        this.dataSource = dataSource;
        this.jdbcTemplate = jdbcTemplate;
    }

    @SneakyThrows
    @Override
    public List<User> customQueryUsingConnection(String namePattern)
    {
        //创建数据库连接
        Connection connection = this.dataSource.getConnection();
        //创建 PreparedStatement 预处理语句
        PreparedStatement pstmt = connection.prepareStatement("select * from user_inf where name like ?");
        pstmt.setString(1, namePattern);
        //执行查询
        ResultSet rs = pstmt.executeQuery();
        List<User> userList = new ArrayList<>();
        //遍历结果集,封装对象
        while (rs.next())
        {
            userList.add(new User(
                    rs.getInt("user_id"),
                    rs.getString("name"),
                    rs.getString("password"),
                    rs.getInt("age")
            ));
        }
        return userList;
    }

    @Override
    public List<User> customQueryUsingTemplate(String namePattern)
    {
        //直接执行查询
        List<User> userList = this.jdbcTemplate.query(
                "select user_id as id,name ,password,age from user_inf where name like ?",
                //把查询的结果封装起来
                new BeanPropertyRowMapper<>(User.class),
                namePattern
        );
        return userList;
    }
}

UserDaoTest

package cn.ljh.app;

import cn.ljh.app.dao.UserDao;
import cn.ljh.app.domain.User;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.jdbc.repository.query.Modifying;
import org.springframework.data.jdbc.repository.query.Query;
import org.springframework.test.annotation.Rollback;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * author JH
 */
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class UserDaoTest
{
    @Autowired
    private UserDao userDao;

    // 继承 CrudRepository 接口后,就已经有通用的 CRUD 操作,无需自己来书写这些方法==============
    //添加user对象
    @ParameterizedTest
    @CsvSource({"aa,xxx,2", "bb,xxx,3"})
    public void testSave(String name, String password, int age)
    {
        //没有id,save就是添加
        User user = userDao.save(new User(null, name, password, age));
        System.err.println(user);
    }

    //根据id修改对象
    @ParameterizedTest
    @CsvSource({"13,aaa,xxxx,22"})
    public void testUpdate(Integer id, String name, String password, int age)
    {
        //有id,save就是修改
        User user = userDao.save(new User(id, name, password, age));
        System.err.println(user);
    }

    //根据id删除用户对象
    @ParameterizedTest
    @ValueSource(ints = {14})
    public void testDelete(Integer id)
    {
        userDao.deleteById(id);
    }

    //根据id查询对象
    @ParameterizedTest
    @ValueSource(ints = {1})
    public void testFindById(Integer id)
    {
        Optional<User> user = userDao.findById(id);
    }


    //方法名关键字查询---------全自动=====================================================
    //根据名字模糊查询
    @ParameterizedTest
    @ValueSource(strings = {"孙%", "%精"})
    public void testFindByNameLike(String namePattern)
    {
        List<User> users = userDao.findByNameLike(namePattern);
        users.forEach(System.err::println);
    }

    //根据年龄大小进行范围查询
    @ParameterizedTest
    @ValueSource(ints = {500, 10})
    public void testFindByAgeGreaterThan(int startAge)
    {
        List<User> users = userDao.findByAgeGreaterThan(startAge);
        users.forEach(System.err::println);
    }

    //根据年龄大小进行范围查询
    @ParameterizedTest
    @ValueSource(ints = {20})
    public void testFindByAgeLessThan(int age)
    {
        List<User> users = userDao.findByAgeLessThan(age);
        users.forEach(System.err::println);
    }

    //根据年龄区间进行范围查询
    @ParameterizedTest
    @CsvSource({"15,20", "500,1000"})
    public void testFindByAgeBetween(int startAge, int endAge)
    {
        List<User> users = userDao.findByAgeBetween(startAge, endAge);
        users.forEach(System.err::println);
    }


    //@Query 查询 --->自己定义查询语句-----半自动=====================================================================
    //rowMapperClass 或 rowMapperRef 是用来做自定义映射,查询出来的User对象的数据,映射到Student对象的属性上面去都可以,因为是自定义的。

    //根据密码模糊查询
    @ParameterizedTest
    @ValueSource(strings = {"niu%", "%3"})
    public void testFindBySql(String passwordPattern)
    {
        List<User> users = userDao.findBySql(passwordPattern);
        users.forEach(System.err::println);
    }

    //根据年龄范围修改名字
    @ParameterizedTest
    @CsvSource({"牛魔王aa,800,1000"})
    @Transactional
    @Rollback(false)
    public void testUpdateNameByAge(String name, int startAge, int endAge)
    {
        int i = userDao.updateNameByAge(name, startAge, endAge);
    }

    //自己定义的接口,用来实现全手动的查询===================================================================================

    //通过名字进行模糊查询,使用 dataSource
    @ParameterizedTest
    @ValueSource(strings = {"孙%"})
    public void testCustomQueryUsingConnection(String namePattern)
    {
        List<User> users = userDao.customQueryUsingConnection(namePattern);
        users.forEach(System.err::println);
    }

    //通过名字进行模糊查询,使用 jdbcTemplate
    @ParameterizedTest
    @ValueSource(strings = {"孙%"})
    public void testCustomQueryUsingTemplate(String namePattern)
    {
        List<User> users = userDao.customQueryUsingTemplate(namePattern);
        users.forEach(System.err::println);
    }
}

application.properties

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springboot?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456

pom.xml

<?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.4.5</version>
    </parent>
    <groupId>cn.ljh</groupId>
    <artifactId>Spring_Data_JDBC</artifactId>
    <version>1.0.0</version>
    <name>Spring_Data_JDBC</name>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <!-- 导入 spring data jdbc -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1040775.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

uniapp:tabBar点击后设置动画效果

APP端不支持dom操作&#xff0c;也不支持active伪类&#xff0c;绞尽脑汁也没办法给uniapp原生的tabBar点击加动画效果&#xff0c;所以最终只能舍弃原生tabBar&#xff0c;改用自定义tabBar。 自定义tabBar的原理是&#xff0c;页面的上部分分别是tabBar对应的页面组件&#…

论文速览【序列模型 seq2seq】—— 【Ptr-Net】Pointer Networks

标题&#xff1a;Pointer Networks文章链接&#xff1a;Pointer Networks参考代码&#xff08;非官方&#xff09;&#xff1a;keon/pointer-networks发表&#xff1a;NIPS 2015领域&#xff1a;序列模型&#xff08;RNN seq2seq&#xff09;改进 / 深度学习解决组合优化问题【…

StableAudio-大模型创作音乐的工具

音乐产业即将发生革命。 今天Stability AI&#xff0c;开源人工智能工具和模型之王&#xff0c;例如Stable DIffusion和StableLM&#xff0c;推出Stable Audio&#xff0c;其首款用于音乐和声音生成的人工智能产品。 音乐行业是出了名的难以进入。即使您有才华和动力&#x…

RFID技术在质量控制和生产追溯中的关键应用

在现代制造业中&#xff0c;质量控制和生产追溯是确保产品质量和合规性的关键环节。RFID技术已经成为实现这一目标的强大工具。本文将探讨RFID技术在质量控制和生产追溯中的关键应用&#xff0c;以及如何利用它来提高生产效率、确保产品质量和满足合规性要求。 生产过程追溯 …

Android11 适配

一、修改targetSdkVersion为30 将build.gradle的目标版本targetSdkVersion修改为30&#xff08;Android 11&#xff09; targetSdkVersion 30Android11的改变改变主要影响以Adnroid11 为目标版本的应用&#xff08;targetSdkVersion>30才有影响&#xff09;&#xff0c;和所…

OpenCV实现模板匹配和霍夫线检测,霍夫圆检测

一&#xff0c;模板匹配 1.1代码实现 import cv2 as cv import numpy as np import matplotlib.pyplot as plt from pylab import mplmpl.rcParams[font.sans-serif] [SimHei]#图像和模板的读取 img cv.imread("cat.png") template cv.imread(r"E:\All_in\o…

18672-2014 枸杞 学习记录

声明 本文是学习GB-T 18672-2014 枸杞. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了枸杞的质量要求、试验方法、检验规则、标志、包装、运输和贮存。 本标准适用于经干燥加工制成的各品种的枸杞成熟果实。 2 规范性引用文件…

无代码解决信息孤岛,云表实现软件开发"书同文,车同轨"

什么是信息孤岛&#xff1f;信息孤岛就是一个组织或系统内部的信息资源无法与其他部分或外部系统共享、互操作&#xff0c;从而使得这些信息无法在整个组织或系统中发挥最大作用的现象。这种现象通常发生在不同部门、不同业务领域或不同系统之间&#xff0c;导致信息重复、浪费…

精彩回顾 | 迪捷软件亮相2023世界智能网联汽车大会

2023年9月24日&#xff0c;2023世界智能网联汽车大会&#xff08;以下简称大会&#xff09;在北京市圆满落幕。迪捷软件北京参展之行圆满收官。 本次大会由工业和信息化部、公安部、交通运输部、中国科学技术协会、北京市人民政府联合主办&#xff0c;是我国首个经国务院批准的…

【编码魔法师系列_构建型1.2 】工厂方法模式(Factory Method)

学会设计模式&#xff0c;你就可以像拥有魔法一样&#xff0c;在开发过程中解决一些复杂的问题。设计模式是由经验丰富的开发者们&#xff08;GoF&#xff09;凝聚出来的最佳实践&#xff0c;可以提高代码的可读性、可维护性和可重用性&#xff0c;从而让我们的开发效率更高。通…

基于微信小程序的竞赛管理平台设计与实现(开题报告+任务书+源码+lw+ppt +部署文档+讲解)

文章目录 前言运行环境说明学生微信端的主要功能有&#xff1a;竞赛负责人的主要功能&#xff1a;管理员的主要功能有&#xff1a;具体实现截图详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考论文参考源码获取 前…

33 排序链表

排序链表 题解1 STL - multiset题解2 归并【自顶向下】题解3 归并【自底向上】自底向上&#xff1a;子串长度 l 从1开始&#xff0c;合并后的串长度*2&#xff0c;11 -> 22 -> 44 ->... 给你链表的头结点 head &#xff0c;请将其按 升序 排列并返回 排序后的链表 …

如何选择一款高性价比的便携式明渠流量计

如何选择一款精度高、测量准确、易操作的便携式明渠流量计 如何选择一款精度高、测量准确、易操作的便携式明渠流量计 便携式明渠流量计&#xff1a;是一款对现有在线水监测系统中流量监测的对比装置。该便携式明渠流量计实现了比对在线系统的液位误差及流量误差。引导式的操作…

基于微信小程序的背单词学习激励系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言用户微信端的主要功能有&#xff1a;管理员的主要功能有&#xff1a;具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉…

2023年思维100秋季赛报名中,比赛安排、阶段、形式和5年真题资源

家有小学生的魔都的爸爸妈妈们&#xff0c;上海市含金量比较高的奥数比赛——思维100秋季比赛正在报名中。如果你想让你的孩子多个证书、多个经历、以赛促学&#xff0c;来了解一下吧。 一、思维100比赛是什么&#xff1f; 思维100是原来的“中环杯”&#xff0c;全称"中…

ChatGPT实战-Embeddings打造定制化AI智能客服

本文介绍Embeddings的基本概念&#xff0c;并使用最少但完整的代码讲解Embeddings是如何使用的&#xff0c;帮你打造专属AI聊天机器人&#xff08;智能客服&#xff09;&#xff0c;你可以拿到该代码进行修改以满足实际需求。 ChatGPT的Embeddings解决了什么问题&#xff1f; …

蓝桥杯 题库 简单 每日十题 day10

01 最少砝码 最少砝码 问题描述 你有一架天平。现在你要设计一套砝码&#xff0c;使得利用这些砝码 可以出任意小于等于N的正整数重量。那么这套砝码最少需要包含多少个砝码&#xff1f; 注意砝码可以放在天平两边。 输入格式 输入包含一个正整数N。 输出格式 输出一个整数代表…

面部情绪识别Facial Emotion Recognition:从表情到情绪的全面解析与代码实现

面部情绪识别&#xff08;FER&#xff09;是指根据面部表情对人类情绪进行识别和分类的过程。通过分析面部特征和模式&#xff0c;机器可以有依据地推测一个人的情绪状态。这一面部识别子领域是一个高度跨学科的领域&#xff0c;它借鉴了计算机视觉、机器学习和心理学的见解。 …

蓝桥杯每日一题2023.9.25

4406. 积木画 - AcWing题库 题目描述 分析 在完成此问题前可以先引入一个新的问题 291. 蒙德里安的梦想 - AcWing题库 我们发现16的二进制是 10000 15的二进制是1111 故刚好我们可以从0枚举到1 << n(相当于二的n次方的二进制表示&#xff09; 注&#xff1a;奇数个0…

学生用什么光的灯最好?2023最适合学生用的台灯推荐

学生当然用全光谱的台灯最好。全光谱台灯主要还是以护眼台灯为主&#xff0c;因为不仅色谱丰富&#xff0c;贴近自然色的全光谱色彩&#xff0c;通常显色指数都能达到Ra95以上&#xff0c;显色能力特别强&#xff0c;而且还具有其他防辐射危害、提高光线舒适度的特性&#xff0…