Spring Data开发手册|手摸手教你简化持久层开发工作
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)
导包
编写配置文件
<?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>
编写实体类和映射
@Entity
@Table(name="t_user")
public class User {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int userId;
private String userName;
private String password;
}
编写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);
}
测试
ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("config/bean-base.xml");
//获取DAO的对象
UserRepository userRepository=applicationContext.getBean(UserRepository.class);
User users=userRepository.findByUserId(1);
}
通过名字来确定方法
代码演示:
举例如下
:
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);
}
注意:一般情况下不会通过名字直接来写相应的方法,因为如果条件过多那么这个时候我们就存在名字特别长的问题
通过注解的模式来实现查询
代码演示:
举例如下
:
/**
* 查询所有 没有条件直接查询
* @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 查询
代码演示:
举例如下
:
/**
* 通过
* @Title: findUserAll11
* @Description: TODO
* @param: @return
* @return: List<User>
* @throws
*/
@Query(nativeQuery=true,value="select * from t_user")
public List<User> findUserAll11();
增删改的玩法
代码演示:
添加业务逻辑 增加事务环境
:
@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的对象
:
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);
}
测试
:
@Test
public void testHelloWorld() throws Exception {
ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("config/bean-base.xml");
//获取DAO的对象
UserService userService=applicationContext.getBean(UserService.class);
userService.insert("小羽","做程序的");
}
使用框架中提供的增删改查的方法
代码演示:
提供的是Repository
:
public interface UserRepository extends CrudRepository<User,Integer>{
}
分页和排序
代码演示:
提供的Repository
:
public interface UserRepository extends PagingAndSortingRepository<User,Integer>{
}
测试
:
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
:
public interface UserRepository extends JpaRepository<User,Integer>{
}
测试
:
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的开发知识,只希望能对大家有所帮助,谢谢大家的支持!
写作秉持初心,致力于让每一位互联网人共同进步。
所见所领,皆是生活。慢慢来,努力一点,你我共同成长...
华为开发者空间发布
让每位开发者拥有一台云主机
- 点赞
- 收藏
- 关注作者
评论(0)