king

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

king 运维技术 2022-11-07 446浏览 0

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

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

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

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

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

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

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

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

Spring Data是什么

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

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

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

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

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

Spring Data能干什么

主要用途:

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

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

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

导包

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

编写配置文件

<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="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-placeholderlocation="classpath:config/db.properties"/>

<!--配置c3p0的连接池-->
<beanid="dataSource"class="com.mchange.v2.c3p0.ComboPooledDataSource">
<propertyname="driverClass"value="${driverClass}"></property>
<propertyname="jdbcUrl"value="${url}"></property>
<propertyname="user"value="${user}"></property>
<propertyname="password"value="${password}"></property>
<propertyname="acquireIncrement"value="${acquireIncrement}"></property>
<propertyname="maxPoolSize"value="${maxPoolSize}"></property>
<propertyname="minPoolSize"value="${minPoolSize}"></property>
<propertyname="maxStatements"value="${maxStatements}"></property>
</bean>

<!--配置JPA实现产品的适配器-->
<beanid="jpaVendorAdapter"class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
</bean>

<!--配置EntityManager对象-->

<beanid="entityManagerFactory"class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<!--注入数据源-->
<propertyname="dataSource"ref="dataSource"></property>
<!--扫描entity包的-->
<propertyname="packagesToScan"value="com.qy.helloworld"></property>
<!--注入JPA实现产品的适配器-->
<propertyname="jpaVendorAdapter"ref="jpaVendorAdapter"></property>
<!--配置的是Hibernate的其他配置除了连接数据库4大要素之外的其余配置-->
<propertyname="jpaProperties">
<props>
<!--是否自动创建表-->
<propkey="hibernate.hbm2ddl.auto">update</prop>
<!--配置是否展示SQL-->
<propkey="hibernate.show_sql">true</prop>
<!--是否格式化SQL-->
<propkey="hibernate.format_sql">true</prop>
<!--连接数据库的方言-->
<propkey="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
</props>
</property>
</bean>


<!--配置事务环境-->

<beanid="jpaTransactionManager"class="org.springframework.orm.jpa.JpaTransactionManager">
<!--注入dataSource-->
<propertyname="dataSource"ref="dataSource"></property>
<!--注入entityManagerFactory对象-->
<propertyname="entityManagerFactory"ref="entityManagerFactory"></property>
</bean>

<!--使用事务-->
<tx:annotation-driventransaction-manager="jpaTransactionManager"/>

<!--配置AOP的自动代理-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

<!--配置Spring的包扫描-->
<context:component-scanbase-package="com.qy.helloworld"></context:component-scan>

<!--Springdata的包的扫描这里的扫描扫描的是DAO层所在的位置-->
<jpa:repositoriesbase-package="com.qy.helloworld"entity-manager-factory-ref="entityManagerFactory"transaction-manager-ref="jpaTransactionManager"></jpa:repositories>

</beans>

编写实体类和映射

@Entity
@Table(name="t_user")
publicclassUser{

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
privateintuserId;

privateStringuserName;

privateStringpassword;
}

编写Repository类

publicinterfaceUserRepositoryextendsRepository<User,Integer>{
/**
*这个的意思是通过id找用户
*@Title:getByUserId
*@Description:TODO
*@param:@paramuserId
*@param:@return
*@return:User
*@throws
*/
publicUsergetByUserId(intuserId);
}

测试

ClassPathXmlApplicationContextapplicationContext=newClassPathXmlApplicationContext("config/bean-base.xml");
//获取DAO的对象
UserRepositoryuserRepository=applicationContext.getBean(UserRepository.class);
Userusers=userRepository.findByUserId(1);
}

通过名字来确定方法

代码演示:

举例如下:

publicinterfaceUserRepositoryextendsRepository<User,Integer>{
/**
*这个的意思是通过id找用户
*@Title:getByUserId
*@Description:TODO
*@param:@paramuserId
*@param:@return
*@return:User
*@throws
*/
publicUsergetByUserId(intuserId);

/**
*记住查询的开头只能是get或者find开头By:通过什么查询
*@Title:findByUserId
*@Description:TODO
*@param:@paramuserId
*@param:@return
*@return:User
*@throws
*/
publicUserfindByUserId(intuserId);

/**
*通过用户名的模糊查询
*@Title:findByUserNameLike
*@Description:TODO
*@param:@paramuserName
*@param:@return
*@return:List<User>
*@throws
*/
publicList<User>findByUserNameLike(StringuserName);

/**
*通过用户名和密码的Like来进行查询
*@Title:findByUserNameLikeAndPasswordLike
*@Description:TODO
*@param:@paramuserName
*@param:@return
*@return:List<User>
*@throws
*/
publicList<User>findByUserNameLikeAndPasswordLike(StringuserName,Stringpassword);
/**
*用户名和密码like然后id小于一个范围
*@Title:findByUserNameLikeAndPasswordLikeAndUserIdLessThan
*@Description:TODO
*@param:@paramuserName
*@param:@parampassword
*@param:@paramuserId
*@param:@return
*@return:List<User>
*@throws
*/
publicList<User>findByUserNameLikeAndPasswordLikeAndUserIdLessThan(StringuserName,Stringpassword,intuserId);
}

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

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

代码演示:

举例如下:

/**
*查询所有没有条件直接查询
*@Title:findUserAll
*@Description:TODO
*@param:@return
*@return:List<User>
*@throws
*/
@Query("fromUser")
publicList<User>findUserAll();

/**
*通过id来查找数据参数直接拼接到后面
*@Title:findUserById
*@Description:TODO
*@param:@paramuserId
*@param:@return
*@return:List<User>
*@throws
*/
@Query("fromUseruwhereu.userId<3")
publicList<User>findUserById();
/**
*通过id查询存在占位符的情况
*@Title:findUserById1
*@Description:TODO
*@param:@paramuserId
*@param:@return
*@return:List<User>
*@throws
*/
@Query("fromUseruwhereu.userId<?")
publicList<User>findUserById1(intuserId);

/**
*多条件的查询可以指定当前的参数映射的这个位置
*@Title:getUserByNameAndId
*@Description:TODO
*@param:@paramuserName
*@param:@paramuserId
*@param:@return
*@return:User
*@throws
*/
@Query("fromUseruwhereu.userId=?2andu.userName=?1")
publicUsergetUserByNameAndId(StringuserName,intuserId);

/**
*模糊查询的时候动态拼接上%的问题
*@Title:findUserByLike1
*@Description:TODO
*@param:@paramuserName
*@param:@return
*@return:List<User>
*@throws
*/
@Query("fromUseruwhereu.userNamelikeconcat('%',?,'%')")
publicList<User>findUserByLike1(StringuserName);

写本地的SQL 查询

代码演示:

举例如下:

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

增删改的玩法

代码演示:

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

@Service
@Transactional//提供一个事务的环境
publicclassUserService{

@Autowired
privateUserRepositoryuserRepository=null;

/**
*数据的更新
*@Title:update
*@Description:TODO
*@param:@paramuserName
*@param:@parampassword
*@param:@paramuserId
*@return:void
*@throws
*/
publicvoidupdate(StringuserName,Stringpassword,intuserId){
userRepository.update(userName,password,userId);
}


publicvoiddelete(intuserId){
userRepository.delete(userId);
}

publicvoidinsert(StringuserName,Stringpassword){
userRepository.insert(userName,password);
}

}

编写repository的对象:

publicinterfaceUserRepositoryextendsRepository<User,Integer>{
/**
*实现增删改的方法
*@Title:add
*@Description:TODO
*@param:@paramuserName
*@param:@parampassword
*@return:void
*@throws
*/
@Modifying//这个注解的作用表示的是更新数据
@Query("updateUserusetu.userName=?,u.password=?whereu.userId=?")
publicvoidupdate(StringuserName,Stringpassword,intuserId);

/**
*更新数据
*@Title:delete
*@Description:TODO
*@param:@paramuserId
*@return:void
*@throws
*/
@Modifying//这个注解的作用表示的是更新数据
@Query("deleteUseruwhereu.userId=?")
publicvoiddelete(intuserId);
/**
*添加数据
*@Title:insert
*@Description:TODO
*@param:@paramuserName
*@param:@parampassword
*@return:void
*@throws
*/
@Modifying//这个注解的作用表示的是更新数据
@Query(nativeQuery=true,value="insertintot_user(userName,password)values(?,?)")
publicvoidinsert(StringuserName,Stringpassword);

}

测试:

@Test
publicvoidtestHelloWorld()throwsException{

ClassPathXmlApplicationContextapplicationContext=newClassPathXmlApplicationContext("config/bean-base.xml");
//获取DAO的对象
UserServiceuserService=applicationContext.getBean(UserService.class);

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

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

代码演示:

提供的是Repository:

publicinterfaceUserRepositoryextendsCrudRepository<User,Integer>{

分页和排序

代码演示:

提供的Repository:

publicinterfaceUserRepositoryextendsPagingAndSortingRepository<User,Integer>{

测试:

publicclassTest001{


@Test
publicvoidtestPaging()throwsException{
ClassPathXmlApplicationContextapplicationContext=newClassPathXmlApplicationContext("config/bean-base.xml");
//获取DAO的对象
UserRepositoryuserRepository=applicationContext.getBean(UserRepository.class);
/**
*第一个参数:当前的页的页数是多少页数是从0开始的第二页:2-1
*第二个参数:表示的是每一页条目数
*/
Page<User>pages=userRepository.findAll(newPageRequest(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:@throwsException
*@return:void
*@throws
*/
@Test
publicvoidtestSort()throwsException{
ClassPathXmlApplicationContextapplicationContext=newClassPathXmlApplicationContext("config/bean-base.xml");
//获取DAO的对象
UserRepositoryuserRepository=applicationContext.getBean(UserRepository.class);
/**
*排序
*第一个参数:升序或者降序Direction.ASC/DESC
*第二个参数:排序的这个列
*/
List<User>users=(List<User>)userRepository.findAll(newSort(Direction.DESC,"userId"));

System.out.println(users);
}

/**
*排序后分页
*@Title:testSortAndPaging
*@Description:TODO
*@param:@throwsException
*@return:void
*@throws
*/
@Test
publicvoidtestSortAndPaging()throwsException{
ClassPathXmlApplicationContextapplicationContext=newClassPathXmlApplicationContext("config/bean-base.xml");
//获取DAO的对象
UserRepositoryuserRepository=applicationContext.getBean(UserRepository.class);

Page<User>pages=userRepository.findAll(newPageRequest(2-1,2,newSort(Direction.DESC,"userId")));

System.out.println(pages.getContent());
}

JpaRepository的使用

代码演示:

提供的repository:

publicinterfaceUserRepositoryextendsJpaRepository<User,Integer>{

测试:

publicclassTest001{
@Test
publicvoidtestPaging()throwsException{
ClassPathXmlApplicationContextapplicationContext=newClassPathXmlApplicationContext("config/bean-base.xml");
//获取DAO的对象
UserRepositoryuserRepository=applicationContext.getBean(UserRepository.class);

//longcount=userRepository.count();

//Useruser=userRepository.findOne(15);
//user.setUserName("小羽");

//保存或者更新数据
//userRepository.saveAndFlush(user);


List<User>users=userRepository.findAll();

//批处理
userRepository.deleteInBatch(users);

//System.out.println("统计:"+count);
}
}

结语

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

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

继续浏览有关 数据库运维 的文章
发表评论