Java笔记:JDBC传统数据库访问和SpringData入门

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: Java笔记:JDBC传统数据库访问和SpringData入门

一、SpringData简介

SpringData提供一致的,大家都熟悉的编程模型,为了简化数据库的访问。


子项目:


  1. Spring Data JPA:减少数据层的开发量
  2. Spring Data Mongo DB:基于分布式数据层的数据库,在大数据层用的比较多
  3. Spring Data Redis:开源,由C语言编写的,支持网络、内存,而且可以持久化的,提供非常多的语言支持
  4. Spring Data Solr:高性能 搜索功能 对查询性能优化

二、传统方式访问数据库

1、JDBC

  • Connection
  • Statement
  • ResultSet
  • TestCase

项目准备

  1. 新建maven 项目
  2. 选择maven-archetype-quickstart
  3. 设置GAV
  4. 添加依赖:
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>8.0.20</version>
</dependency>
<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.11</version>
  <scope>test</scope>
</dependency>
  1. 数据库
create database spring_data;
create table student(
    id int not null auto_increment,
    name varchar(20) not null,
    age int not null,
    primary key(id)
);
insert into student(name, age) values("刘备", 40);
insert into student(name, age) values("关羽", 30);
insert into student(name, age) values("张飞", 20);

6.开发JDBCUtil工具类

获取Connection,关闭Connection,Statement,ResultSet

db.properties

jdbc.driverClass = com.mysql.cj.jdbc.Driver
jdbc.username = root
jdbc.password = 123456
jdbc.url = jdbc:mysql://127.0.0.1:3306/data
package com.mouday.util;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
/**
 * JDBC工具类
 * 1. 获取Connection
 * 2. 释放资源
 */
public class JDBCUtil {
    // 配置型内容建议放在配置文件中
    private static final String driverClass = "com.mysql.cj.jdbc.Driver";
    private static final String username = "root";
    private static final String password = "123456";
    private static final String url = "jdbc:mysql://127.0.0.1:3306/data";
    /**
     * 获取Connection
     *
     * @return
     */
    public static Connection getConnection() throws Exception {
        // 读取配置文件
        InputStream inputStream = JDBCUtil.class.getClassLoader().getResourceAsStream("db.properties");
        Properties properties = new Properties();
        properties.load(inputStream);
        String driverClass = properties.getProperty("jdbc.driverClass");
        String username = properties.getProperty("jdbc.username");
        String password = properties.getProperty("jdbc.password");
        String url = properties.getProperty("jdbc.url");
        Class.forName(driverClass);
        Connection connection = DriverManager.getConnection(url, username, password);
        return connection;
    }
    /**
     * 关闭链接
     *
     * @param resultSet
     * @param statement
     * @param connection
     */
    public static void release(ResultSet resultSet,
                               Statement statement,
                               Connection connection) {
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

注意事项:

配置的属性放在配置文件中

实体类

package com.mouday.domain;
/**
 * 学生实体类
 */
public class Student {
    private Integer id;
    private String  name;
    private Integer age;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

接口类

package com.mouday.dao;
import com.mouday.domain.Student;
import java.util.List;
/**
 * 学生访问接口
 */
public interface StudentDao {
    /**
     * 获取所有学生
     * @return
     */
    List<Student> query();
    /**
     * 插入数据
     * @param student
     * @return
     */
    Integer insert(Student student);
}

实现类

package com.mouday.dao.impl;
import com.mouday.dao.StudentDao;
import com.mouday.domain.Student;
import com.mouday.util.JDBCUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
/**
 * 学生访问接口实现类
 */
public class StudentDaoImpl implements StudentDao {
    @Override
    public List<Student> query() {
        List<Student> students = new ArrayList<>();
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        String sql = "select id, name, age from student";
        Student student;
        try {
            connection = JDBCUtil.getConnection();
            statement = connection.prepareStatement(sql);
            resultSet = statement.executeQuery();
            while (resultSet.next()) {
                Integer id = resultSet.getInt("id");
                String name = resultSet.getString("name");
                Integer age = resultSet.getInt("age");
                student = new Student();
                student.setId(id);
                student.setName(name);
                student.setAge(age);
                students.add(student);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.release(resultSet, statement, connection);
        }
        return students;
    }
    @Override
    public Integer insert(Student student) {
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        String sql = "insert into student (name, age) values (?, ?)";
        Integer id = null;
        try {
            connection = JDBCUtil.getConnection();
            statement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
            statement.setString(1, student.getName());
            statement.setInt(2, student.getAge());
            statement.executeUpdate();
            // 获取自增id
            resultSet = statement.getGeneratedKeys();
            if (resultSet.next()) {
                id = resultSet.getInt(1);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.release(resultSet, statement, connection);
        }
        return id;
    }
}

测试类

package com.mouday.util;
import org.junit.Assert;
import org.junit.Test;
import java.sql.Connection;
public class JDBCUtilTest {
    @Test
    public void  testGetConnection() throws Exception{
        Connection connection = JDBCUtil.getConnection();
        Assert.assertNotNull(connection);
    }
}
package com.mouday.dao.impl;
import com.mouday.dao.StudentDao;
import com.mouday.domain.Student;
import org.junit.Test;
import java.util.List;
public class StudentDaoImplTest {
    @Test
    public void testQuery() {
        StudentDao studentDao = new StudentDaoImpl();
        List<Student> students = studentDao.query();
        System.out.println(students);
    }
    @Test
    public void testInsert() {
        StudentDao studentDao = new StudentDaoImpl();
        Student student = new Student();
        student.setName("曹操");
        student.setAge(50);
        Integer id = studentDao.insert(student);
        System.out.println(id);
    }
}

2、Spring JdbcTemplate

(1)添加依赖

<!-- spring-jdbc -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-jdbc</artifactId>
  <version>5.3.1</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>5.3.1</version>
</dependency>

(2)配置beans.xml

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://127.0.0.1:3306/data"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </bean>
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <bean id="studentDao" class="com.mouday.dao.impl.StudentDaoSpringJdbcImpl">
        <property name="jdbcTemplate" ref="jdbcTemplate"/>
    </bean>
</beans>

(3)Dao实现类

package com.mouday.dao.impl;
import com.mouday.dao.StudentDao;
import com.mouday.domain.Student;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
/**
 * 学生访问接口实现类
 */
public class StudentDaoSpringJdbcImpl implements StudentDao {
    private JdbcTemplate jdbcTemplate;
    public JdbcTemplate getJdbcTemplate() {
        return jdbcTemplate;
    }
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
    @Override
    public List<Student> query() {
        List<Student> students = new ArrayList<>();
        String sql = "select id, name, age from student";
        jdbcTemplate.query(sql, new RowCallbackHandler() {
            @Override
            public void processRow(ResultSet resultSet) throws SQLException {
                Integer id = resultSet.getInt("id");
                String name = resultSet.getString("name");
                Integer age = resultSet.getInt("age");
                Student student = new Student();
                student.setId(id);
                student.setName(name);
                student.setAge(age);
                students.add(student);
            }
        });
        return students;
    }
    @Override
    public Integer insert(Student student) {
        String sql = "insert into student (name, age) values (?, ?)";
        KeyHolder keyHolder = new GeneratedKeyHolder();
        jdbcTemplate.update(new PreparedStatementCreator() {
            @Override
            public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
                PreparedStatement ps = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
                ps.setString(1, student.getName());
                ps.setInt(2, student.getAge());
                return ps;
            }
        }, keyHolder);
        return keyHolder.getKey().intValue();
    }
}

测试类

package com.mouday;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
public class DataSourceTest {
    ApplicationContext context = null;
    @Before
    public void setup() {
        System.out.println("StudentDaoSpringJdbcImplTest.setup");
        context = new ClassPathXmlApplicationContext("beans.xml");
    }
    @After
    public void tearDown() {
        System.out.println("StudentDaoSpringJdbcImplTest.tearDown");
        context = null;
    }
    @Test
    public void testDataSource() {
        DataSource dataSource = context.getBean("dataSource", DataSource.class);
        System.out.println(dataSource);
        Assert.assertNotNull(dataSource);
    }
    @Test
    public void testJdbcTemplate() {
        JdbcTemplate jdbcTemplate = context.getBean("jdbcTemplate", JdbcTemplate.class);
        System.out.println(jdbcTemplate);
        Assert.assertNotNull(jdbcTemplate);
    }
}
package com.mouday.dao.impl;
import com.mouday.dao.StudentDao;
import com.mouday.domain.Student;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
public class StudentDaoSpringJdbcImplTest {
    ApplicationContext context = null;
    StudentDao studentDao = null;
    @Before
    public void setup() {
        System.out.println("StudentDaoSpringJdbcImplTest.setup");
        context = new ClassPathXmlApplicationContext("beans.xml");
        studentDao = context.getBean("studentDao", StudentDao.class);
    }
    @After
    public void tearDown() {
        System.out.println("StudentDaoSpringJdbcImplTest.tearDown");
        context = null;
        studentDao = null;
    }
    @Test
    public void testQuery() {
        List<Student> students = studentDao.query();
        System.out.println(students);
    }
    @Test
    public void testInsert() {
        Student student = new Student();
        student.setName("曹操");
        student.setAge(50);
        Integer id = studentDao.insert(student);
        System.out.println(id);
    }
}

3、优缺点分析

弊端:

Dao有大量代码

DaoImpl有重复代码

三、SpringData 快速开始

1、开发环境搭建

依赖

 <dependency>
  <groupId>org.springframework.data</groupId>
  <artifactId>spring-data-jpa</artifactId>
  <version>2.4.0</version>
</dependency>
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-entitymanager</artifactId>
  <version>5.4.24.Final</version>
</dependency>

配置beans-jpa.xml

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:jpa="http://www.springframework.org/schema/data/jpa"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/data/jpa
        http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    <!--1 配置数据源-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://127.0.0.1:3306/data"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
    </bean>
    <!--2 配置EntityManagerFactory-->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
        </property>
        <property name="packagesToScan" value="com.mouday"/>
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
            </props>
        </property>
    </bean>
    <!--3 配置事务管理器-->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>
    <!--4 配置支持注解的事务-->
    <tx:annotation-driven transaction-manager="transactionManager"/>
    <!--5 配置spring data-->
    <jpa:repositories base-package="com.mouday" entity-manager-factory-ref="entityManagerFactory"/>
    <context:component-scan base-package="com.mouday"/>
</beans>

定义实体

package com.mouday.domain;
import javax.persistence.*;
/**
 * 雇员表 先开发实体->自动生成数据表
 */
@Entity
public class Employee {
    private Integer id;
    private String name;
    private Integer age;
    // 主键自增
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    @Id
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    @Column(length = 20)
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

自动建表测试

package com.mouday;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
public class SpringDataJpaTest {
    ApplicationContext context = null;
    @Before
    public void setup() {
        System.out.println("StudentDaoSpringJdbcImplTest.setup");
        context = new ClassPathXmlApplicationContext("beans-jpa.xml");
    }
    @After
    public void tearDown() {
        System.out.println("StudentDaoSpringJdbcImplTest.tearDown");
        context = null;
    }
    @Test
    public void testEntityManagerFactory() {
    }
}

2、Spring Data JPA 开发

定义接口

package com.mouday.repository;
import com.mouday.domain.Employee;
import org.springframework.data.repository.Repository;
public interface EmployeeRepository extends Repository<Employee, Integer> {
    public Employee findByName(String name);
}

插入数据

insert into employee(name, age) values("刘备", 40);
insert into employee(name, age) values("关羽", 30);
insert into employee(name, age) values("张飞", 20);
package com.mouday.repository;
import com.mouday.domain.Employee;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class EmployeeRepositoryTest {
    ApplicationContext context = null;
    EmployeeRepository repository = null;
    @Before
    public void setup() {
        System.out.println("StudentDaoSpringJdbcImplTest.setup");
        context = new ClassPathXmlApplicationContext("beans-jpa.xml");
        repository = context.getBean(EmployeeRepository.class);
    }
    @After
    public void tearDown() {
        System.out.println("StudentDaoSpringJdbcImplTest.tearDown");
        context = null;
    }
    @Test
    public void testFindByName() {
        Employee employee = repository.findByName("刘备");
        System.out.println(employee);
    }
}

SpringDATA:


  1. Repository核心
  2. Repository Definition 定义
  3. Repository Query Specifications 查询规则 规范 技术参数
  4. Query Annotation 查询注解
  5. Update/Delete/Transaction 对事务的细粒度优秀支持

四、SpringData JPA 进阶

Responsitory类的定义

public interface Repository<T,ID extends Serializable>{
}

1)Responsitory是一个空接口,标记接口

没有包含方法的声明接口

2)我们定义的接口

public interface EmployeeRepository extends Repository<Employee, Integer>{
}

表示此接口纳入spring管理,需按一定规则定义方法

或者使用注解方式定义

@RepositoryDefinition(domainClass = Employee.class, idClass = Integer.class)
public interface EmployeeRepository {
}

Repository继承体系

CrudRepository                    # 实现了CRUD相关方法
    - PagingAndSortingRepository  # 实现了分页排序方法
        - JpaRepository           # 实现了Jpa规范相关方法
JpaSpecificationExecutor

Repository查询方法定义规则和使用

package com.mouday.repository;
import com.mouday.domain.Employee;
import org.springframework.data.repository.RepositoryDefinition;
import java.util.List;
@RepositoryDefinition(domainClass = Employee.class, idClass = Integer.class)
public interface EmployeeRepository
{
    // where name = ?
    public Employee findByName(String name);
    // where name like ?% and age > ?
    List<Employee> findByNameStartingWithAndAgeGreaterThan(String name, Integer age);
    // where name like %? and age > ?
    List<Employee> findByNameEndingWithAndAgeGreaterThan(String name, Integer age);
}

测试

package com.mouday.repository;
import com.mouday.domain.Employee;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
public class EmployeeRepositoryTest {
    ApplicationContext context = null;
    EmployeeRepository repository = null;
    @Before
    public void setup() {
        System.out.println("StudentDaoSpringJdbcImplTest.setup");
        context = new ClassPathXmlApplicationContext("beans-jpa.xml");
        repository = context.getBean(EmployeeRepository.class);
    }
    @After
    public void tearDown() {
        System.out.println("StudentDaoSpringJdbcImplTest.tearDown");
        context = null;
    }
    @Test
    public void testFindByName() {
        Employee employee = repository.findByName("刘备");
        System.out.println(employee);
    }
    @Test
    public void testFindByNameStartingWithAndAgeGreaterThan() {
        List<Employee> employees = repository.findByNameStartingWithAndAgeGreaterThan("刘", 10);
        System.out.println(employees);
    }
    @Test
    public void testFindByNameEndingWithAndAgeGreaterThan() {
        List<Employee> employees = repository.findByNameEndingWithAndAgeGreaterThan("羽", 10);
        System.out.println(employees);
    }
}

命名规则的弊端

  • 方法名比较长
  • 复杂查询很难实现

Query查询注解

1、在Respository方法中使用,不需要遵循查询方法命名规则

2、只需要将@Query定义在Respository中的方法之上即可

3、命名参数及索引参数的使用

4、本地查询

package com.mouday.repository;
import com.mouday.domain.Employee;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.RepositoryDefinition;
import org.springframework.data.repository.query.Param;
import java.util.List;
@RepositoryDefinition(domainClass = Employee.class, idClass = Integer.class)
public interface EmployeeRepository
{
    // where name = ?
    public Employee findByName(String name);
    // where name like ?% and age > ?
    List<Employee> findByNameStartingWithAndAgeGreaterThan(String name, Integer age);
    // where name like %? and age > ?
    List<Employee> findByNameEndingWithAndAgeGreaterThan(String name, Integer age);
    // where name in (?...) and age > ?
    List<Employee> findByNameInAndAgeGreaterThan(List<String> names, Integer age);
    @Query("select o from Employee o where id = (select max(id) from Employee t1)")
    Employee getEmployeeByMaxId();
    @Query("select o from Employee o where o.name = ?1 and o.age =?2")
    Employee getEmployeeByName1(String name, Integer age);
    @Query("select o from Employee o where o.name = :name and o.age = :age")
    Employee getEmployeeByName2(@Param("name") String name, @Param("age") Integer age);
    @Query("select o from Employee o where o.name like %?1%")
    Employee getEmployeeByNameLike1(String name);
    @Query("select o from Employee o where o.name like %:name%")
    Employee getEmployeeByNameLike2(@Param("name") String name);
    // 开启原生查询
    @Query(nativeQuery=true, value = "select count(*) from employee")
    Integer getEmployeeCount();
}

测试

package com.mouday.repository;
import com.mouday.domain.Employee;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.ArrayList;
import java.util.List;
public class EmployeeRepositoryTest {
    ApplicationContext context = null;
    EmployeeRepository repository = null;
    @Before
    public void setup() {
        System.out.println("StudentDaoSpringJdbcImplTest.setup");
        context = new ClassPathXmlApplicationContext("beans-jpa.xml");
        repository = context.getBean(EmployeeRepository.class);
    }
    @After
    public void tearDown() {
        System.out.println("StudentDaoSpringJdbcImplTest.tearDown");
        context = null;
    }
    @Test
    public void testFindByName() {
        Employee employee = repository.findByName("刘备");
        System.out.println(employee);
    }
    @Test
    public void testFindByNameStartingWithAndAgeGreaterThan() {
        List<Employee> employees = repository.findByNameStartingWithAndAgeGreaterThan("刘", 10);
        System.out.println(employees);
    }
    @Test
    public void testFindByNameEndingWithAndAgeGreaterThan() {
        List<Employee> employees = repository.findByNameEndingWithAndAgeGreaterThan("羽", 10);
        System.out.println(employees);
    }
    @Test
    public void testFindByNameInAndAgeGreaterThan() {
        List<String> names = new ArrayList<>();
        names.add("刘备");
        names.add("张飞");
        List<Employee> employees = repository.findByNameInAndAgeGreaterThan(names, 10);
        System.out.println(employees);
    }
    @Test
    public void testGetEmployeeByMaxId() {
        Employee employee = repository.getEmployeeByMaxId();
        System.out.println(employee);
    }
    @Test
    public void testGetEmployeeByName1() {
        Employee employee = repository.getEmployeeByName1("刘备", 40);
        System.out.println(employee);
    }
    @Test
    public void testGetEmployeeByName2() {
        Employee employee = repository.getEmployeeByName2("刘备", 40);
        System.out.println(employee);
    }
    @Test
    public void testGetEmployeeByNameLike1() {
        Employee employee = repository.getEmployeeByNameLike1("刘");
        System.out.println(employee);
    }
    @Test
    public void testGetEmployeeByNameLike2() {
        Employee employee = repository.getEmployeeByNameLike2("刘");
        System.out.println(employee);
    }
    @Test
    public void testGetEmployeeCount() {
        Integer total = repository.getEmployeeCount();
        System.out.println(total);
    }
}

事务在 Spring Data 中的应用:

  1. 事务一般是在 service 层,保证事务的完整性

2)注解的使用

@Query 查询

@Modifying 修改 更新和删除必用

@Transactional 事务 更新和删除必用

package com.mouday.repository;
import com.mouday.domain.Employee;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.RepositoryDefinition;
import org.springframework.data.repository.query.Param;
import java.util.List;
@RepositoryDefinition(domainClass = Employee.class, idClass = Integer.class)
public interface EmployeeRepository
{
    // 修改操作
    @Modifying
    @Query("update Employee o set o.name = :name where id = :id")
    void updateNameById(@Param("id") Integer id, @Param("name") String name);
}
package com.mouday.service;
import com.mouday.repository.EmployeeRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
@Service
public class EmployeeService {
    @Autowired
    private EmployeeRepository repository;
    @Transactional
    public void update(Integer id, String name){
        repository.updateNameById(id, name);
    }
}

测试

package com.mouday.service;
import com.mouday.repository.EmployeeRepository;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class EmployeeServiceTest {
    ApplicationContext context = null;
    EmployeeService service = null;
    @Before
    public void setup() {
        System.out.println("StudentDaoSpringJdbcImplTest.setup");
        context = new ClassPathXmlApplicationContext("beans-jpa.xml");
        service = context.getBean(EmployeeService.class);
    }
    @After
    public void tearDown() {
        System.out.println("StudentDaoSpringJdbcImplTest.tearDown");
        context = null;
    }
    @Test
    public void testUpdate(){
        service.update(1, "曹操");
    }
}

五、SpringData JPA 高级

Repository接口

public interface Repository<T, ID> {
}

CrudRepository接口

public interface CrudRepository<T, ID> extends Repository<T, ID> {
    <S extends T> S save(S entity);
    <S extends T> Iterable<S> saveAll(Iterable<S> entities);
    Optional<T> findById(ID id);
    boolean existsById(ID id);
    Iterable<T> findAll();
    Iterable<T> findAllById(Iterable<ID> ids);
    long count();
    void deleteById(ID id);
    void delete(T entity);
    void deleteAll(Iterable<? extends T> entities);
    void deleteAll();
}

PagingAndSortingRepository接口

public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> {
    Iterable<T> findAll(Sort sort);
    Page<T> findAll(Pageable pageable);
}

JpaRepository接口

public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
    @Override
    List<T> findAll();
    @Override
    List<T> findAll(Sort sort);
    @Override
    List<T> findAllById(Iterable<ID> ids);
    @Override
    <S extends T> List<S> saveAll(Iterable<S> entities);
    void flush();
    <S extends T> S saveAndFlush(S entity);
    void deleteInBatch(Iterable<T> entities);
    void deleteAllInBatch();
    T getOne(ID id);
    @Override
    <S extends T> List<S> findAll(Example<S> example);
    @Override
    <S extends T> List<S> findAll(Example<S> example, Sort sort);
}

代码实例

CrudRepository

package com.mouday.repository;
import com.mouday.domain.Employee;
import org.springframework.data.repository.CrudRepository;
public interface EmployeeCrudRepository extends CrudRepository<Employee, Integer> {
}

PagingAndSortingRepository

package com.mouday.repository;
import com.mouday.domain.Employee;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.PagingAndSortingRepository;
/**
 * 分页,排序
 */
public interface EmployeePagingAndSortingRepository extends PagingAndSortingRepository<Employee, Integer> {
}
package com.mouday.repository;
import com.mouday.domain.Employee;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import java.util.ArrayList;
import java.util.List;
public class EmployeePagingAndSortingRepositoryTest {
    ApplicationContext context = null;
    EmployeePagingAndSortingRepository repository = null;
    @Before
    public void setup() {
        System.out.println("StudentDaoSpringJdbcImplTest.setup");
        context = new ClassPathXmlApplicationContext("beans-jpa.xml");
        repository = context.getBean(EmployeePagingAndSortingRepository.class);
    }
    @After
    public void tearDown() {
        System.out.println("StudentDaoSpringJdbcImplTest.tearDown");
        context = null;
    }
    @Test
    public void testPaging() {
        // page从0开始
        Pageable pageable = PageRequest.of(1, 5);
        Page<Employee> page = repository.findAll(pageable);
        System.out.println(page);
        System.out.println("总数" + page.getTotalElements());
        System.out.println("当前页面数据" + page.getContent());
    }
    @Test
    public void testSort() {
        // 排序
        Sort.Order order = new Sort.Order(Sort.Direction.DESC, "id");
        Sort sort = Sort.by(order);
        // page从0开始
        Pageable pageable = PageRequest.of(1, 5, sort);
        Page<Employee> page = repository.findAll(pageable);
        System.out.println(page);
        System.out.println("总数" + page.getTotalElements());
        System.out.println("当前页面数据" + page.getContent());
    }
}

JpaRepository

package com.mouday.repository;
import com.mouday.domain.Employee;
import org.springframework.data.jpa.repository.JpaRepository;
public interface EmployeeJpaRepository extends JpaRepository<Employee, Integer> {
}
package com.mouday.repository;
import com.mouday.domain.Employee;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class EmployeeJpaRepositoryTest {
    ApplicationContext context = null;
    EmployeeJpaRepository repository = null;
    @Before
    public void setup() {
        System.out.println("StudentDaoSpringJdbcImplTest.setup");
        context = new ClassPathXmlApplicationContext("beans-jpa.xml");
        repository = context.getBean(EmployeeJpaRepository.class);
    }
    @After
    public void tearDown() {
        System.out.println("StudentDaoSpringJdbcImplTest.tearDown");
        context = null;
    }
    @Test
    public void testFind() {
        Employee employee = repository.getOne(1);
        System.out.println(employee);
    }
}

JpaSpecificationExecutor

package com.mouday.repository;
import com.mouday.domain.Employee;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface EmployeeJpaSpecificationExecutor extends JpaRepository<Employee, Integer>, JpaSpecificationExecutor<Employee> {
}
package com.mouday.repository;
import com.mouday.domain.Employee;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import javax.persistence.criteria.*;
public class EmployeeJpaSpecificationExecutorTest {
    ApplicationContext context = null;
    EmployeeJpaSpecificationExecutor repository = null;
    @Before
    public void setup() {
        System.out.println("StudentDaoSpringJdbcImplTest.setup");
        context = new ClassPathXmlApplicationContext("beans-jpa.xml");
        repository = context.getBean(EmployeeJpaSpecificationExecutor.class);
    }
    @After
    public void tearDown() {
        System.out.println("StudentDaoSpringJdbcImplTest.tearDown");
        context = null;
    }
    /**
     * 条件 age > 10
     * 排序 order by id desc
     * 分页 offset 0 limit 5
     */
    @Test
    public void testFind() {
        /**
         * root 查询类型
         * query 查询条件
         * criteriaBuilder 构建Predicate
         */
        Specification specification = new Specification<Employee>() {
            @Override
            public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                Path path = root.get("age");
                return criteriaBuilder.gt(path, 10);
            }
        };
        Sort sort = Sort.by(Sort.Direction.DESC, "id");
        Pageable pageable = PageRequest.of(0, 5, sort);
        Page<Employee> page = repository.findAll(specification, pageable);
        System.out.println(page);
        System.out.println("总数" + page.getTotalElements());
        System.out.println("当前页面数据" + page.getContent());
    }
}

总结

  1. Spring Data概览
  2. 传统方式访问数据库
  3. Spring Data快速起步
  4. Spring Data JPA进阶
  5. Spring Data JPA高级
相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
2月前
|
XML Java 数据库连接
性能提升秘籍:如何高效使用Java连接池管理数据库连接
在Java应用中,数据库连接管理至关重要。随着访问量增加,频繁创建和关闭连接会影响性能。为此,Java连接池技术应运而生,如HikariCP。本文通过代码示例介绍如何引入HikariCP依赖、配置连接池参数及使用连接池高效管理数据库连接,提升系统性能。
70 5
|
9天前
|
自然语言处理 Java
Java中的字符集编码入门-增补字符(转载)
本文探讨Java对Unicode的支持及其发展历程。文章详细解析了Unicode字符集的结构,包括基本多语言面(BMP)和增补字符的表示方法,以及UTF-16编码中surrogate pair的使用。同时介绍了代码点和代码单元的概念,并解释了UTF-8的编码规则及其兼容性。
81 60
|
19天前
|
Java 数据库连接 数据库
springboot java.lang.ClassNotFoundException: dm.jdbc.driver.DmDriver应该如何解决
通过上述步骤,可以有效解决Spring Boot项目中遇到的 `java.lang.ClassNotFoundException: dm.jdbc.driver.DmDriver`问题。确保在项目中正确添加达梦数据库的JDBC驱动依赖,并在配置文件中正确配置数据源信息,是解决此问题的关键。通过这些方法,可以确保Spring Boot项目能够正确连接达梦数据库并正常运行。
142 31
|
1月前
|
Java 开发者 微服务
Spring Boot 入门:简化 Java Web 开发的强大工具
Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
67 6
Spring Boot 入门:简化 Java Web 开发的强大工具
|
2月前
|
JSON Java 关系型数据库
Java更新数据库报错:Data truncation: Cannot create a JSON value from a string with CHARACTER SET 'binary'.
在Java中,使用mybatis-plus更新实体类对象到mysql,其中一个字段对应数据库中json数据类型,更新时报错:Data truncation: Cannot create a JSON value from a string with CHARACTER SET 'binary'.
157 4
Java更新数据库报错:Data truncation: Cannot create a JSON value from a string with CHARACTER SET 'binary'.
|
1月前
|
监控 架构师 Java
Java虚拟机调优的艺术:从入门到精通####
本文作为一篇深入浅出的技术指南,旨在为Java开发者揭示JVM调优的神秘面纱,通过剖析其背后的原理、分享实战经验与最佳实践,引领读者踏上从调优新手到高手的进阶之路。不同于传统的摘要概述,本文将以一场虚拟的对话形式,模拟一位经验丰富的架构师向初学者传授JVM调优的心法,激发学习兴趣,同时概括性地介绍文章将探讨的核心议题——性能监控、垃圾回收优化、内存管理及常见问题解决策略。 ####
|
2月前
|
监控 安全 Java
Java中的多线程编程:从入门到实践####
本文将深入浅出地探讨Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的摘要形式,本文将以一个简短的代码示例作为开篇,直接展示多线程的魅力,随后再详细解析其背后的原理与实现方式,旨在帮助读者快速理解并掌握Java多线程编程的基本技能。 ```java // 简单的多线程示例:创建两个线程,分别打印不同的消息 public class SimpleMultithreading { public static void main(String[] args) { Thread thread1 = new Thread(() -> System.out.prin
|
2月前
|
Java 大数据 API
14天Java基础学习——第1天:Java入门和环境搭建
本文介绍了Java的基础知识,包括Java的简介、历史和应用领域。详细讲解了如何安装JDK并配置环境变量,以及如何使用IntelliJ IDEA创建和运行Java项目。通过示例代码“HelloWorld.java”,展示了从编写到运行的全过程。适合初学者快速入门Java编程。
|
2月前
|
安全 Java 调度
Java中的多线程编程入门
【10月更文挑战第29天】在Java的世界中,多线程就像是一场精心编排的交响乐。每个线程都是乐团中的一个乐手,他们各自演奏着自己的部分,却又和谐地共同完成整场演出。本文将带你走进Java多线程的世界,让你从零基础到能够编写基本的多线程程序。
39 1
|
2月前
|
Java 程序员 数据库连接
Java中的异常处理:从入门到精通
在Java编程的海洋中,异常处理是一艘不可或缺的救生艇。它不仅保护你的代码免受错误数据的侵袭,还能确保用户体验的平稳航行。本文将带你领略异常处理的风浪,让你学会如何在Java中捕捉、处理和预防异常,从而成为一名真正的Java航海家。