Spring Data 简单学习
前言
苦逼的学生党终于快迎接放假了~~~ 虽然临近期末,明明还没预习但还是想搞一些奇奇怪怪的…………最近,有一个自己的想法想在暑假搞出来以便将来可以写在简历之类的,因为学过一些Spring全家桶,就顺手练一下还有做一下学习笔记。这里的案例是为了那个项目准备的,所以会融入到那个项目中,还有我会尽可能多打注释的。另外,立个flag,暑假尽可能写博客记录一下学习生活。
这一篇主要是关于 Spring Data 的学习笔记。
- 案例地址(欢迎大家支持给颗star):https://github.com/FunriLy/LiveChat
Spring Data 介绍
注意:这里的介绍来源于网络!而且,等会用到的是主要是JPA部分
看了这么多专业的介绍,其实Spring Data项目旨在为大家提供一种通用的编码模式,统一我们的API。spring Data 项目的目的是为了简化构建基于 Spring 框架应用的数据访问计数,包括非关系数据库、Map-Reduce 框架、云数据服务等等;另外也包含对关系数据库的访问支持。
Spring Data 包含多个子项目:
- Commons - 提供共享的基础框架,适合各个子项目使用,支持跨数据库持久化
- Hadoop - 基于 Spring 的 hadoop 作业配置和一个 POJO 编程模型的 MapReduce 作业
- Key-Value - 集成了 Redis 和 Riak ,提供多个常用场景下的简单封装
- Document - 集成文档数据库:CouchDB 和 MongoDB 并提供基本的配置映射和资料库支持
- Graph - 集成 Neo4j 提供强大的基于 POJO 的编程模型
- Graph Roo AddOn - Roo support for Neo4j
- JDBC Extensions - 支持 Oracle RAD、高级队列和高级数据类型
- JPA - 简化创建 JPA 数据访问层和跨存储的持久层功能
- Mapping - 基于 Grails 的提供对象映射框架,支持不同的数据库
- Examples - 示例程序、文档和图数据库
- Guidance - 高级文档
看了这么多专业的介绍,其实Spring Data项目旨在为大家提供一种通用的编码模式,统一我们的API。
初学SpringData
利用SpringBoot框架集合SpringData框架!
1. 资源配置
pom.xml配置:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<!--SpringBoot其他配置就不罗列了,主要是与Data有关的-->
<!--JPA 操作数据库-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--MySQL-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
application.properties配置:
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/XXXXXX?characterEncoding=utf8&useSSL=false
spring.datasource.username=XXXXXX
spring.datasource.password=XXXXXX
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
2. 数据库建表和Model层建立
Model层建立User实体:
@Entity //实体类,利用对象关系映射生成数据库表
@Table(name = "users", schema = "livechat", catalog = "")
public class User implements Serializable{
private static final long serialVersionUID = 1l;
@Id
private String id;
@Column(nullable = false, name = "name")
private String name;
}
数据库建表:
CREATE TABLE `users` (
`id` varchar(25) NOT NULL,
`name` varchar(8) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
3. 继承Repository接口
Repository是一个标记接口,继承该接口的Bean被Spring容器识别为一个RepositoryBean:
1. 可以使用 Query 注解查询
1. spring data repository 接口中的方法默认只有查询和保存,没有更新和删除的事务
1. SpringData的命名规范:(find | get | read) + By + field + ( + 关键字 + field )
如,findByName、findByNameAndId
public interface UserRepositoy extends Repository<User, String> {
// SQL = select * from users where name = ?
public User findByName(String name);
public User getById(String id);
public User save(User user);
/**
* 关于 * ,IDEA语法报错但不影响运行,应该是IDEA本身提示的问题
* 但是有一个语法提示感觉有点别扭,所以我将它注释了
*/
// @Query(value = "select * from users u where u.name = :name", nativeQuery = true)
// public User myselect(@Param("name") String name);
}
我将单元测试全部集中到一起了,所以将在后面进行测试。
4. 继承CrudRepository
由于Repository
接口的局限性,所以我一般都是用CrudRepository
。但Repository
可以自定义接口。CrudRepository
接口继承于 Repository 接口,并新增了简单的增、删、查等方法。
方法列表:
long count();
boolean exists(Integer arg0);
<S extends StudentPO> S save(S arg0);
<S extends StudentPO> Iterable<S> save(Iterable<S> arg0);
void delete(Integer arg0);
void delete(Iterable<? extends StudentPO> arg0);
void delete(StudentPO arg0);
void deleteAll();
StudentPO findOne(Integer arg0);
Iterable<StudentPO> findAll();
Iterable<StudentPO> findAll(Iterable<Integer> arg0);
UserDao.java:
public interface UserDao extends CrudRepository<User, String> {
//可以用 @Query 注解添加自己的事务方法
}
5. 单元测试
因为案例用的是SpringBoot 1.5.x,JUnit单元测试优化,并且换注解@SpringApplicationConfiguration(Application.class)
为@SpringBootTest
。
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class UserDaoTest {
@Autowired
private UserRepositoy repositoy;
@Autowired
private UserDao userDao;
@Test
public void test_reposity(){
//先在数据库中添加一条记录{id='123456', name='funrily'}
String name = "funrily";
System.out.println("====测试Reposity===");
User user = repositoy.findByName("funrily");
System.out.println(user.toString());
// User next = repositoy.myselect("funrily");
// System.out.println(next.toString());
//
// repositoy.save(new User("654321", "fangrui"));
// next = repositoy.findByName("fangrui");
// System.out.println(next.toString());
}
/**
* 查询表种记录的数量
*/
@Test
public void test_count(){
long cout = userDao.count();
System.out.println("count = " + cout);
}
@Test
public void test_exists(){
//根据主键判断是否存在
boolean isExist = userDao.exists("123456");
System.out.println("IsExist :" + isExist);
}
@Test
public void test_save(){
//单个保存
User user = new User("127.0.0.1", "host");
System.out.println(userDao.save(user));
//批量保存
User user1 = new User("1", "1");
User user2 = new User("2", "2");
User user3 = new User("3", "3");
User user4 = new User("4", "4");
List<User> users = new ArrayList<>();
users.add(user1);
users.add(user2);
users.add(user3);
users.add(user4);
System.out.println("批量保存:" + userDao.save(users));
}
@Test
public void test_find(){
//通过id查询一个记录
User user = userDao.findOne("127.0.0.1");
System.out.println("通过id查找一个记录:" + user);
//根据id列表查询,其内部实际上使用了 in 关键字
List<String> idList = new ArrayList<>();
idList.add("1");
idList.add("2");
System.out.println("根据id列表查询:" + userDao.findAll(idList));
//查找所有的记录
System.out.println("所有的记录:" + userDao.findAll());
}
/**
* 关于delete的单元测试需要在上面的单元测试通过后
* 数据库中有相应的记录才可以执行成功
*/
@Test
public void test_delete(){
//通过id删除一条记录
userDao.delete("127.0.0.1");
System.out.println("通过id删除一条记录后,记录是否存在:" + userDao.exists("127.0.0.1"));
//删除某个特定的记录
User user = userDao.findOne("123456"); //查找一个记录
if (user != null && user.getId() != null && !user.getId().equals("")){
userDao.delete(user);
System.out.println("通过id删除一条记录后,记录是否存在:" + userDao.exists("123456"));
}
//根据id列表删除记录
List<User> userList = new ArrayList<>();
userList.add(userDao.findOne("1"));
userList.add(userDao.findOne("2"));
userDao.delete(userList);
//删除所有的记录
userDao.deleteAll();
}
}
补充点
@Query 注解
使用@Query注解可以自定义JPQL语句,语句可以实现更灵活的查询。@Modifying 注解
可以通过自定义的JPQL来完成update和delete操作。在@Query注解中编写JPQL语句,但必须使用@Modify进行修饰,主要功能是通知SpringData,这是一个Update或者Delete。
Spring-data的能力远不止本文提到的这些,这里的使用只是介绍了常见的使用方式。诸如@Modifying操作、分页排序、原生SQL支持以及与Spring MVC的结合使用等等内容,我了解还不够,如果以后有时间再来补坑吧~
参考资料
http://blog.csdn.net/z69183787/article/details/30265243
http://blog.csdn.net/luckyzhoustar/article/details/49362951