1. ORM
ORM——Object Relational Mapping,即对象关系映射,实质是表示内存中的对象与关系型数据库之间的映射关系。
2. JPA
JPA全称Java Persistence API,可以通过注解或者XML描述对象-关系表之间的映射关系,并将实体对象持久化到数据库中。
3. JPA的功能
1. 提供ORM映射元数据,JPA支持XML和注解两种元数据的形式,元数据描述对象与表之间的映射关系,ORM框架则根据这种映射关系将实体对象映射到数据库中。
2. 提供持久层的API,用来操作实体对象,执行CURD操作,ORM框架替开发者完成所有的事情,开发者无需关注JDBC以及SQL代码的编写。
3. 提供JPQL(Java Persistence Query Language),即Java持久化查询语言,一种面向对象而非面向数据库的查询语言进行数据查询,避免程序的SQL语句紧密耦合。
总结:JPA仅仅是一种规范,也就是说JPA仅仅定义了一些接口,而Hibernate是实现JPA接口的ORM框架。即JPA是ORM规范,Hibernate是实现这种规范的一种ORM框架。
![]() |
4. Spring data jpa
Spring data jpa是spring提供的一套简化JPA开发的框架,按照约定编写好DAO层接口,就可以在不实现接口的情况下实现对数据库的访问和操作,同时提供了很多处理CURD的功能,如分页,排序,复杂的查询等。Spring data JPA可以理解为JPA规范的再次封装抽象,底层使用的是Hibernate的JPA技术实现。
![]() |
3.1 按照约定命名规则
序号 | 关键字 | 方法名称 | Sql语句where字句(JPQL Snippet) |
1 | And | findByLastnameAndFirstname | where Lastname = ? and Firstname = ? |
2 | Or | findByLastnameOrFirstname | where Lastname = ? or Firstname = ? |
3 | Is,Equals | findByFirstname,findByFirstnIs,findByFirstnameEquals | where Firstname = ? |
4 | Between | findByStartDateBetween | where startDate between ? and ? |
5 | LessThan | findByAgeLessThan | where age < ? |
6 | LessThanEquals | findByAgeLessThanEquals | where age <= ? |
7 | GreaterThan | findByAgeGreater | where age > ? |
8 | GreaterThanEquals | findByAgeGreaterEquals | where age >= ? |
9 | After | findByStartDateAfter | where startDate > ? |
10 | Before | findByStartDateBefore | where startDate < ? |
11 | IsNull | findByAgeIsNull | where Age is null |
12 | isNotNull,NotNull | findByAge(Is)NotNull | where Age is not null |
13 | Like | findByFirstnameLike | where firstname like ? |
14 | NotLike | findByFirstnameeNotLike | where firstname not like ? |
15 | StartingWith | findByFirstnameStartingWith | where firstname like "?%" |
16 | EndingWith | findByFirstnameEndingWith | where firstname like "%?" |
17 | Containing | findByFirstnameContaining | where firstname like "%?%" |
18 | OrderBy | findByAgeOrderByLastnameDesc | where name age = ? order by Lastname desc |
19 | Not | findByAgeNot | where age <> ? |
20 | In | findByAgeIn(Collection<Age> ages) | where age in (?) |
21 | NotIn | findByAgeNotIn(Collection<Age> ages) | where age not in (?) |
22 | True | findByActiveTrue | where active = true |
23 | False | findByActiveFalse | where active = false |
24 | IgnoreCase | findByFirstnameIgnoreCase | where UPPER(firstname) = UPPER(?) |
创建测试数据库
CREATE DATABASE testDB;
CREATE TABLE `test_jpa` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`first_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`last_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`sex` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`email` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`age` int(12) NOT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
示例代码:
public interface TestJpaRepositories extends JpaRepository<TestJpa,Integer> {
//根据firstName与LastName查找(两者必须在数据库有)
TestJpa findByFirstNameAndLastName(String firstName, String lastName);
//根据firstName或LastName查找(两者其一有就行)
TestJpa findByLastNameOrFirstName(String lastTestName,String firstName);
//根据firstName查找它是否存在数据库里<类似与以下关键字>
//TestJpa findByFirstName(String firstName);
TestJpa findByFirstNameIs(String firstName);
//在Age数值age到age2之间的数据
List<TestJpa> findByAgeBetween(Integer age, Integer age2);
//小于指定age数值之间的数据
List<TestJpa> findByAgeLessThan(Integer age);
//小于等于指定age数值的数据
List<TestJpa> findByAgeLessThanEqual(Integer age);
//大于指定age数值之间的数据
List<TestJpa> findByAgeGreaterThan(Integer age);
//大于或等于指定age数值之间的数据
List<TestJpa> findByAgeGreaterThanEqual(Integer age);
//在指定age数值之前的数据类似关键字<LessThan>
List<TestJpa> findByAgeAfter(Integer age);
//在指定age数值之后的数据类似关键字<GreaterThan>
List<TestJpa> findByAgeBefore(Integer age);
//返回age字段为空的数据
List<TestJpa> findByAgeIsNull();
//返回age字段不为空的数据
List<TestJpa> findByAgeNotNull();
/**
* 该关键字我一度以为是类似数据库的模糊查询,
* 但是我去官方文档看到它里面并没有通配符。
* 所以我觉得它类似
* TestJpa findByFirstName(String firstName);
* @see https://docs.spring.io/spring-data/jpa/docs/2.1.5.RELEASE/reference/html/#jpa.repositories
*/
TestJpa findByFirstNameLike(String firstName);
//同上
List<TestJpa> findByFirstNameNotLike(String firstName);
//查找数据库中指定类似的名字(如:输入一个名字"M" Jpa会返回多个包含M开头的名字的数据源)<类似数据库模糊查询>
List<TestJpa> findByFirstNameStartingWith(String firstName);
//查找数据库中指定不类似的名字(同上)
List<TestJpa> findByFirstNameEndingWith(String firstName);
//查找包含的指定数据源(这个与以上两个字段不同的地方在与它必须输入完整的数据才可以查询)
List<TestJpa> findByFirstNameContaining(String firstName);
//根据age选取所有的数据源并按照LastName进行升序排序
List<TestJpa> findByAgeOrderByLastName(Integer age);
//返回不是指定age的所有数据
List<TestJpa> findByAgeNot(Integer age);
//查找包含多个指定age返回的数据
List<TestJpa> findByAgeIn(List<Integer> age);
}
基于Junit4的单元测试(测试有效)
@SpringBootTest
@RunWith(SpringRunner.class)
@Slf4j
public class TestJpaRepositoriesTest {
@Autowired
private TestJpaRepositories repositories;
@Test
public void findByFirstNameAndLastName() {
TestJpa testJpa = repositories.findByFirstNameAndLastName("May", "Eden");
Assert.assertEquals(testJpa.getFirstName(),"May");
}
@Test
public void findByLastNameOrFirstName() {
TestJpa testJpa = repositories.findByLastNameOrFirstName("Geordie", "Eden");
Assert.assertNotEquals(testJpa.getLastName(),"Eden");
}
@Test
public void findByFirstNameIs() {
TestJpa testJpa = repositories.findByFirstNameIs("amy");
Assert.assertNull(testJpa);
}
@Test
public void findByAgeBetween() {
List<TestJpa> testJpaList = repositories.findByAgeBetween(15, 17);
Assert.assertEquals(3,testJpaList.size());
}
@Test
public void findByAgeLessThan() {
List<TestJpa> testJpaList = repositories.findByAgeLessThan(17);
Assert.assertEquals(2,testJpaList.size());
}
@Test
public void findByAgeLessThanEqual() {
List<TestJpa> testJpaList = repositories.findByAgeLessThanEqual(17);
Assert.assertEquals(3,testJpaList.size());
}
@Test
public void findByAgeGreaterThan() {
List<TestJpa> testJpaList = repositories.findByAgeGreaterThan(17);
Assert.assertEquals(2,testJpaList.size());
}
@Test
public void findByAgeGreaterThanEqual() {
List<TestJpa> testJpaList = repositories.findByAgeGreaterThanEqual(17);
Assert.assertEquals(3,testJpaList.size());
}
@Test
public void findByAgeAfter() {
List<TestJpa> testJpaList = repositories.findByAgeAfter(17);
Assert.assertEquals(2,testJpaList.size());
}
@Test
public void findByAgeBefore() {
List<TestJpa> testJpaList = repositories.findByAgeBefore(17);
Assert.assertEquals(2,testJpaList.size());
}
@Test
public void findByAgeIsNull() {
List<TestJpa> testJpaList = repositories.findByAgeIsNull();
Assert.assertEquals(0,testJpaList.size());
}
@Test
public void findByAgeNotNull() {
List<TestJpa> testJpaList = repositories.findByAgeNotNull();
Assert.assertEquals(5,testJpaList.size());
}
@Test
public void findByFirstNameLike() {
TestJpa testJpa = repositories.findByFirstNameLike("May");
Assert.assertNotNull(testJpa);
}
@Test
public void findByFirstNameNotLike() {
}
@Test
public void findByFirstNameStartingWith() {
List<TestJpa> testJpaList = repositories.findByFirstNameStartingWith("May");
Assert.assertEquals(2,testJpaList.size());
}
@Test
public void findByFirstNameEndingWith() {
List<TestJpa> testJpaList = repositories.findByFirstNameEndingWith("Evil");
Assert.assertEquals(0,testJpaList.size());
}
@Test
public void findByFirstNameContaining() {
List<TestJpa> testJpaList = repositories.findByFirstNameContaining("hack");
Assert.assertEquals(0,testJpaList.size());
}
@Test
public void findByAgeOrderByLastName() {
List<TestJpa> testJpaList = repositories.findByAgeOrderByLastName(18);
for (TestJpa testJpaL : testJpaList){
log.info("数据结果"+testJpaL.toString());
}
}
@Test
public void findByAgeNot() {
List<TestJpa> testJpaList = repositories.findByAgeNot(20);
Assert.assertEquals(5,testJpaList.size());
}
@Test
public void findByAgeIn() {
List<TestJpa> testJpaList = repositories.findByAgeIn(Arrays.asList(15, 16));
Assert.assertEquals(2,testJpaList.size());
}
}
总结:ORM是一种架构思想,JPA基于ORM思想定义的一个规范,Hibernate是基于ORM思想,按照JPA规范的一种(框架)实现方式,Spring data JPA可以理解为JPA规范的再次封装抽象,底层使用的是Hibernate的JPA技术实现。