前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring Data开发手册|手摸手教你简化持久层开发工作

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

作者头像
浅羽技术
发布2020-12-07 15:02:14
4550
发布2020-12-07 15:02:14
举报
文章被收录于专栏:浅羽技术

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

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

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

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

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

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

Spring Data是什么

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

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

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

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

Spring Data能干什么

主要用途:

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

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

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

导包

编写配置文件

代码语言:javascript
复制
 <?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>        

编写实体类和映射

代码语言:javascript
复制
@Entity
@Table(name="t_user")
public class User {

 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private int userId;
 
 private String userName;
 
 private String password;
}

编写Repository类

代码语言:javascript
复制
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);
}

测试

代码语言:javascript
复制
ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("config/bean-base.xml");
  //获取DAO的对象
  UserRepository userRepository=applicationContext.getBean(UserRepository.class);
 User users=userRepository.findByUserId(1);
}

通过名字来确定方法

代码演示:

举例如下

代码语言:javascript
复制
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);
}

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

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

代码演示:

举例如下

代码语言:javascript
复制
 /**
     * 查询所有  没有条件直接查询
     * @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);

写本地的SQL 查询

代码演示:

举例如下

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

增删改的玩法

代码演示:

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

代码语言:javascript
复制
 @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);
 }

}

编写repository的对象

代码语言:javascript
复制
 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);
 
}

测试

代码语言:javascript
复制
 @Test
 public void testHelloWorld() throws Exception {
  
  ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("config/bean-base.xml");
  //获取DAO的对象
  UserService userService=applicationContext.getBean(UserService.class);

  userService.insert("小羽","做程序的");
 }

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

代码演示:

提供的是Repository

代码语言:javascript
复制
 public interface UserRepository extends CrudRepository<User,Integer>{

}

分页和排序

代码演示:

提供的Repository

代码语言:javascript
复制
 public interface UserRepository extends PagingAndSortingRepository<User,Integer>{

}

测试

代码语言:javascript
复制
 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());
 }
}

JpaRepository的使用

代码演示:

提供的repository

代码语言:javascript
复制
 public interface UserRepository extends JpaRepository<User,Integer>{

}

测试

代码语言:javascript
复制
 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);
 }
}

结语

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

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

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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-11-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 浅羽的IT小屋 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Spring Data是什么
  • Spring Data能干什么
  • Spring Data的第一个HelloWorld程序(JPA、Hibernate、Spring、SpringMVC、Spring Data)
    • 导包
      • 编写配置文件
        • 编写实体类和映射
          • 编写Repository类
            • 测试
            • 通过名字来确定方法
              • 代码演示:
              • 通过注解的模式来实现查询
                • 代码演示:
                • 写本地的SQL 查询
                  • 代码演示:
                  • 增删改的玩法
                    • 代码演示:
                    • 使用框架中提供的增删改查的方法
                    • 分页和排序
                      • 代码演示:
                      • JpaRepository的使用
                        • 代码演示:
                        • 结语
                        相关产品与服务
                        对象存储
                        对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档