Spring Data开发手册|手摸手教你简化持久层开发工作

简介: Spring Data,是为数据访问提供熟悉且一致的基于Spring的编程模型,同时仍然保留底层数据存储的特殊特性。它是对于数据访问技术,关系数据库和非关系数据库,map-reduce框...

 image.gif

image.gif

Spring Data,是为数据访问提供熟悉且一致的基于Spring的编程模型,同时仍然保留底层数据存储的特殊特性。

它是对于数据访问技术,关系数据库和非关系数据库,map-reduce框架和基于云的数据服务变得容易。Spring Data是一个总括项目,其中包含很多特定于数据库相关的子项目

网络异常,图片无法展示
|
image.gif

首先,先带大家看一下本篇文章的大致介绍。

没目录怎么知道这篇到底有多少干货呢?

    • Spring Data是什么
    • Spring Data能干什么
    • Spring Data的第一个HelloWorld程序
    • 通过名字来确定方法
    • 通过注解的形式来实现查询
    • 写本地的SQL查询
    • 增删改的玩法
    • 使用框架中提供的增删改查的方法
    • 分页和排序
    • JpaRepository的使用

    是不是很清晰呢,现在开始进入正文,一个一个来:

    Spring Data是什么

    我们传统的开发中,我们的整个DAO层的代码上都是相对来说,都是比较复杂的,在这种情况下,Spring团队就考虑到一个问题,能不能开发一个框架,这个框架能够最大限度的减少DAO层的开发呢?

    Spring Data就是为了简化DAO层操作的一个框架

    传统的增删改查在我们的Spring Data中已经实现了,也就是说大部分的DAO层操作部分不用写了,仅仅只是需要编写复杂的业务的调用就可以啦

    网络异常,图片无法展示
    |
    image.gif

    写的这部分的代码,是需要写接口的声明就可以啦,不用写实现,这个实现是自动实现的

    Spring Data能干什么

    主要用途:

      • 传统的增删改查
      • 排序
      • 分页
      • 排序后分页

      即使你需要写DAO,也只是写声明就可以啦,不用写实现

      Spring Data的第一个HelloWorld程序(JPA、Hibernate、Spring、SpringMVC、Spring Data)

      导包

      网络异常,图片无法展示
      |
      image.gif

      编写配置文件

      <?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:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context" 
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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/context
              http://www.springframework.org/schema/context/spring-context.xsd
              http://www.springframework.org/schema/tx
              http://www.springframework.org/schema/tx/spring-tx.xsd
              http://www.springframework.org/schema/aop
              http://www.springframework.org/schema/aop/spring-aop.xsd
              http://www.springframework.org/schema/data/jpa 
              http://www.springframework.org/schema/data/jpa/spring-jpa-1.2.xsd">
              <!--引入Properties文件-->
              <context:property-placeholder location="classpath:config/db.properties"/>
              <!--配置c3p0的连接池-->
              <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
                  <property name="driverClass" value="${driverClass}"></property>
                  <property name="jdbcUrl" value="${url}"></property>
                  <property name="user" value="${user}"></property>
                  <property name="password" value="${password}"></property>
                  <property name="acquireIncrement" value="${acquireIncrement}"></property>
                  <property name="maxPoolSize" value="${maxPoolSize}"></property>
                  <property name="minPoolSize" value="${minPoolSize}"></property>
                  <property name="maxStatements" value="${maxStatements}"></property>
              </bean>
              <!--配置JPA实现产品的适配器-->
              <bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
              </bean>
              <!--配置EntityManager对象-->
              <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
                 <!--注入数据源-->
                 <property name="dataSource" ref="dataSource"></property>
                 <!--扫描entity包的--> 
                 <property name="packagesToScan" value="com.qy.helloworld"></property>
                 <!--注入JPA实现产品的适配器-->
                 <property name="jpaVendorAdapter" ref="jpaVendorAdapter"></property>
                 <!--配置的是Hibernate的其他配置  除了连接数据库4大要素之外的其余配置-->
                 <property name="jpaProperties">
                    <props>
                     <!--是否自动创建表 -->
                     <prop key="hibernate.hbm2ddl.auto">update</prop>
                     <!--配置是否展示SQL-->
                     <prop key="hibernate.show_sql">true</prop>
                     <!--是否格式化SQL-->
                     <prop key="hibernate.format_sql">true</prop>
                     <!--连接数据库的方言-->
                     <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
                  </props>
                 </property>
              </bean>
              <!--配置事务环境-->
              <bean id="jpaTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
                 <!--注入dataSource-->
                 <property name="dataSource" ref="dataSource"></property>
                 <!--注入entityManagerFactory对象-->
                 <property name="entityManagerFactory" ref="entityManagerFactory"></property>
              </bean>
              <!--使用事务-->
              <tx:annotation-driven transaction-manager="jpaTransactionManager"/>
              <!--配置AOP的自动代理-->
              <aop:aspectj-autoproxy></aop:aspectj-autoproxy> 
              <!--配置Spring的包扫描-->
              <context:component-scan base-package="com.qy.helloworld"></context:component-scan>
              <!--Spring data的包的扫描  这里的扫描扫描的是DAO层所在的位置-->
              <jpa:repositories base-package="com.qy.helloworld" entity-manager-factory-ref="entityManagerFactory" transaction-manager-ref="jpaTransactionManager"></jpa:repositories>
      </beans>

      image.gif

      编写实体类和映射

      @Entity
      @Table(name="t_user")
      public class User {
       @Id
       @GeneratedValue(strategy=GenerationType.IDENTITY)
       private int userId;
       private String userName;
       private String password;
      }

      image.gif

      编写Repository类

      public interface UserRepository extends Repository<User,Integer>{
       /**
        * 这个的意思是通过id找用户
        * @Title: getByUserId   
        * @Description: TODO
        * @param: @param userId
        * @param: @return      
        * @return: User      
        * @throws
        */
       public User getByUserId(int userId);
      }

      image.gif

      测试

      ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("config/bean-base.xml");
        //获取DAO的对象
        UserRepository userRepository=applicationContext.getBean(UserRepository.class);
       User users=userRepository.findByUserId(1);
      }

      image.gif

      通过名字来确定方法

      代码演示:

      举例如下

      public interface UserRepository extends Repository<User,Integer>{
       /**
        * 这个的意思是通过id找用户
        * @Title: getByUserId   
        * @Description: TODO
        * @param: @param userId
        * @param: @return      
        * @return: User      
        * @throws
        */
       public User getByUserId(int userId);
       /**
        * 记住查询的开头只能是  get 或者  find 开头   By:通过什么查询
        * @Title: findByUserId   
        * @Description: TODO
        * @param: @param userId
        * @param: @return      
        * @return: User      
        * @throws
        */
       public User findByUserId(int userId);
       /**
        * 通过用户名的模糊查询
        * @Title: findByUserNameLike   
        * @Description: TODO
        * @param: @param userName
        * @param: @return      
        * @return: List<User>      
        * @throws
        */
       public List<User> findByUserNameLike(String userName);
       /**
        * 通过用户名和密码的Like来进行查询
        * @Title: findByUserNameLikeAndPasswordLike   
        * @Description: TODO
        * @param: @param userName
        * @param: @return      
        * @return: List<User>      
        * @throws
        */
       public List<User> findByUserNameLikeAndPasswordLike(String userName,String password);
       /**
        * 用户名和密码like 然后id小于一个范围
        * @Title: findByUserNameLikeAndPasswordLikeAndUserIdLessThan   
        * @Description: TODO
        * @param: @param userName
        * @param: @param password
        * @param: @param userId
        * @param: @return      
        * @return: List<User>      
        * @throws
        */
       public List<User> findByUserNameLikeAndPasswordLikeAndUserIdLessThan(String userName,String password,int userId);
      }

      image.gif

      注意:一般情况下不会通过名字直接来写相应的方法,因为如果条件过多那么这个时候我们就存在名字特别长的问题

      通过注解的模式来实现查询

      代码演示:

      举例如下

      /**
           * 查询所有  没有条件直接查询
           * @Title: findUserAll   
           * @Description: TODO
           * @param: @return      
           * @return: List<User>      
           * @throws
           */
       @Query("from User")
       public List<User> findUserAll();
       /**
        * 通过id来查找数据     参数直接拼接到后面
        * @Title: findUserById   
        * @Description: TODO
        * @param: @param userId
        * @param: @return      
        * @return: List<User>      
        * @throws
        */
       @Query("from User u  where u.userId<3")
       public List<User> findUserById();
       /**
        * 通过id查询存在占位符的情况
        * @Title: findUserById1   
        * @Description: TODO
        * @param: @param userId
        * @param: @return      
        * @return: List<User>      
        * @throws
        */
       @Query("from User u  where u.userId<?")
       public List<User> findUserById1(int userId);
       /**
        * 多条件的查询  可以指定当前的参数映射的这个位置
        * @Title: getUserByNameAndId   
        * @Description: TODO
        * @param: @param userName
        * @param: @param userId
        * @param: @return      
        * @return: User      
        * @throws
        */
       @Query("from User u where u.userId=?2 and u.userName=?1")
       public User getUserByNameAndId(String userName,int userId);
       /**
        * 模糊查询的时候动态拼接上  %的问题
        * @Title: findUserByLike1   
        * @Description: TODO
        * @param: @param userName
        * @param: @return      
        * @return: List<User>      
        * @throws
        */
       @Query("from User u where u.userName like concat ('%',?,'%')")
       public List<User> findUserByLike1(String userName);

      image.gif

      写本地的SQL 查询

      代码演示:

      举例如下

      /**
        * 通过
        * @Title: findUserAll11   
        * @Description: TODO
        * @param: @return      
        * @return: List<User>      
        * @throws
        */
       @Query(nativeQuery=true,value="select * from t_user")
       public List<User> findUserAll11();

      image.gif

      增删改的玩法

      代码演示:

      添加业务逻辑 增加事务环境

      @Service
      @Transactional                  //提供一个事务的环境
      public class UserService {
       @Autowired
       private UserRepository userRepository=null;
       /**
        * 数据的更新
        * @Title: update   
        * @Description: TODO
        * @param: @param userName
        * @param: @param password
        * @param: @param userId      
        * @return: void      
        * @throws
        */
       public void update(String userName,String password,int userId){
        userRepository.update(userName, password, userId);
       }
       public void delete(int userId){
        userRepository.delete(userId);
       }
       public void insert(String userName,String password){
        userRepository.insert(userName, password);
       }
      }

      image.gif

      编写repository的对象

      public interface UserRepository extends Repository<User,Integer>{
       /**
        * 实现增删改的方法
        * @Title: add   
        * @Description: TODO
        * @param: @param userName
        * @param: @param password      
        * @return: void      
        * @throws
        */
       @Modifying    //这个注解的作用表示的是更新数据
       @Query("update User u set u.userName=?,u.password=? where u.userId=?")
       public void update(String userName,String password,int userId);
       /**
        * 更新数据
        * @Title: delete   
        * @Description: TODO
        * @param: @param userId      
        * @return: void      
        * @throws
        */
       @Modifying    //这个注解的作用表示的是更新数据
       @Query("delete User u where u.userId=?")
       public void delete(int userId);
       /**
        * 添加数据
        * @Title: insert   
        * @Description: TODO
        * @param: @param userName
        * @param: @param password      
        * @return: void      
        * @throws
        */
       @Modifying    //这个注解的作用表示的是更新数据
       @Query(nativeQuery=true,value="insert into t_user(userName,password) values(?,?)")
       public void insert(String userName,String password);
      }

      image.gif

      测试

      @Test
       public void testHelloWorld() throws Exception {
        ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("config/bean-base.xml");
        //获取DAO的对象
        UserService userService=applicationContext.getBean(UserService.class);
        userService.insert("小羽","做程序的");
       }

      image.gif

      使用框架中提供的增删改查的方法

      代码演示:

      提供的是Repository

      public interface UserRepository extends CrudRepository<User,Integer>{
      }

      image.gif

      分页和排序

      代码演示:

      提供的Repository

      public interface UserRepository extends PagingAndSortingRepository<User,Integer>{
      }

      image.gif

      测试

      public class Test001 {
       @Test
       public void testPaging() throws Exception {
        ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("config/bean-base.xml");
        //获取DAO的对象
        UserRepository userRepository=applicationContext.getBean(UserRepository.class);
       /**
        * 第一个参数:当前的页的页数是多少  页数是从0开始的   第二页:2-1
        * 第二个参数:表示的是每一页条目数
        */
        Page<User> pages=userRepository.findAll(new PageRequest(2-1,2));
        System.out.println("查询到的数据:"+pages.getContent());
        System.out.println("数据的条目数:"+pages.getSize());
        System.out.println("页数:"+pages.getNumber());
        System.out.println("数据条目的总数:"+pages.getTotalElements());
        System.out.println("一共的页数:"+pages.getTotalPages());
        System.out.println("排序的规则:"+pages.getSort());
       }
       /**
        * 排序
        * @Title: testSort   
        * @Description: TODO
        * @param: @throws Exception      
        * @return: void      
        * @throws
        */
       @Test
       public void testSort() throws Exception {
        ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("config/bean-base.xml");
        //获取DAO的对象
        UserRepository userRepository=applicationContext.getBean(UserRepository.class);
        /**
         * 排序
         * 第一个参数:升序或者降序  Direction.ASC/DESC
         * 第二个参数: 排序的这个列
         */
        List<User> users=(List<User>) userRepository.findAll(new Sort(Direction.DESC,"userId"));
        System.out.println(users);
       }
       /**
        * 排序后分页
        * @Title: testSortAndPaging   
        * @Description: TODO
        * @param: @throws Exception      
        * @return: void      
        * @throws
        */
       @Test
       public void testSortAndPaging() throws Exception {
        ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("config/bean-base.xml");
        //获取DAO的对象
        UserRepository userRepository=applicationContext.getBean(UserRepository.class);
        Page<User> pages=userRepository.findAll(new PageRequest(2-1,2,new Sort(Direction.DESC,"userId")));
        System.out.println(pages.getContent());
       }
      }

      image.gif

      JpaRepository的使用

      代码演示:

      提供的repository

      public interface UserRepository extends JpaRepository<User,Integer>{
      }

      image.gif

      测试

      public class Test001 {
       @Test
       public void testPaging() throws Exception {
        ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("config/bean-base.xml");
        //获取DAO的对象
        UserRepository userRepository=applicationContext.getBean(UserRepository.class);
      //  long count=userRepository.count();
      //  User user=userRepository.findOne(15);
      //  user.setUserName("小羽");
        //保存或者更新数据
      //  userRepository.saveAndFlush(user);
        List<User> users=userRepository.findAll();
        //批处理
        userRepository.deleteInBatch(users);
        //System.out.println("统计:"+count);
       }
      }

      image.gif

      结语

      Spring Data是我们开发中离不开的经常用到的技术,其涉及的技术和知识面其实远不止上面列出的这些。

      后续浅羽会继续更新关于Spring Data的开发知识,只希望能对大家有所帮助,谢谢大家的支持!

      写作秉持初心,致力于让每一位互联网人共同进步。


      image.gif

      image.gif

      点点点,一键三连都在这儿!

      相关文章
      |
      1月前
      |
      Java API 数据库
      构建RESTful API已经成为现代Web开发的标准做法之一。Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐。
      【10月更文挑战第11天】本文介绍如何使用Spring Boot构建在线图书管理系统的RESTful API。通过创建Spring Boot项目,定义`Book`实体类、`BookRepository`接口和`BookService`服务类,最后实现`BookController`控制器来处理HTTP请求,展示了从基础环境搭建到API测试的完整过程。
      48 4
      |
      11天前
      |
      存储 运维 安全
      Spring运维之boot项目多环境(yaml 多文件 proerties)及分组管理与开发控制
      通过以上措施,可以保证Spring Boot项目的配置管理在专业水准上,并且易于维护和管理,符合搜索引擎收录标准。
      23 2
      |
      1月前
      |
      XML Java 数据格式
      提升效率!Spring Boot 开发中的常见失误轻松规避
      本文深入探讨了在 Spring Boot 开发中常见的失误,包括不当使用注解、不良异常处理、低效日志记录等,提供了有效的规避策略,帮助开发者提升代码质量和系统性能,构建更健壮、高效的应用程序。
      |
      16天前
      |
      安全 Java 测试技术
      Java开发必读,谈谈对Spring IOC与AOP的理解
      Spring的IOC和AOP机制通过依赖注入和横切关注点的分离,大大提高了代码的模块化和可维护性。IOC使得对象的创建和管理变得灵活可控,降低了对象之间的耦合度;AOP则通过动态代理机制实现了横切关注点的集中管理,减少了重复代码。理解和掌握这两个核心概念,是高效使用Spring框架的关键。希望本文对你深入理解Spring的IOC和AOP有所帮助。
      31 0
      |
      1月前
      |
      存储 Java API
      如何使用 Java 记录简化 Spring Data 中的数据实体
      如何使用 Java 记录简化 Spring Data 中的数据实体
      37 9
      |
      2月前
      |
      人工智能 开发框架 Java
      重磅发布!AI 驱动的 Java 开发框架:Spring AI Alibaba
      随着生成式 AI 的快速发展,基于 AI 开发框架构建 AI 应用的诉求迅速增长,涌现出了包括 LangChain、LlamaIndex 等开发框架,但大部分框架只提供了 Python 语言的实现。但这些开发框架对于国内习惯了 Spring 开发范式的 Java 开发者而言,并非十分友好和丝滑。因此,我们基于 Spring AI 发布并快速演进 Spring AI Alibaba,通过提供一种方便的 API 抽象,帮助 Java 开发者简化 AI 应用的开发。同时,提供了完整的开源配套,包括可观测、网关、消息队列、配置中心等。
      2259 15
      |
      1月前
      |
      Java 数据库连接 Spring
      【2021Spring编程实战笔记】Spring开发分享~(下)
      【2021Spring编程实战笔记】Spring开发分享~(下)
      26 1
      |
      1月前
      |
      开发框架 Java API
      「SpringBrick快速入门指南」:一款基于Spring Boot的高级插件化开发框架
      「SpringBrick快速入门指南」:一款基于Spring Boot的高级插件化开发框架
      57 0
      |
      1月前
      |
      XML Java 数据格式
      手动开发-简单的Spring基于注解配置的程序--源码解析
      手动开发-简单的Spring基于注解配置的程序--源码解析
      47 0
      |
      1月前
      |
      XML Java 数据格式
      手动开发-简单的Spring基于XML配置的程序--源码解析
      手动开发-简单的Spring基于XML配置的程序--源码解析
      82 0
      下一篇
      无影云桌面