JPA(Java Persistence API),是官方定义的一组接口(也是规范),是为了实现ORM而生的,即Object-Relationl Mapping,它的作用是在数据库和对象之间形成一个映射 ,简单来说就是将数据库中的一行数据映射成一个对象,通过对象去实现数据库的增删改查。
了解更多关于jpa:https://blog.csdn.net/localhost01/article/details/83422893
spirng data jpa是spring提供的一套简化JPA开发的框架,按照约定好的【方法命名规则】写dao层接口,就可以在不写接口实现的情况下,实现对数据库的访问和操作。同时提供了很多除了CRUD之外的功能,如分页、排序、复杂查询等等。
Spring Data JPA 可以理解为 JPA 规范的再次封装抽象,底层还是使用了 Hibernate 的 JPA 技术实现。
了解更多关于spring jpa:https://blog.csdn.net/localhost01/article/details/83422893
下面以继承mongo为例子
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-mongodbartifactId>
dependency>
server:
port: 10211
spring:
data:
mongodb:
host: ip #指定MongoDB服务地址
port: 27017 #指定端口,默认就为27017
database: 数据库名
authentication-database: admin # 登录认证的逻辑库名
username: root #用户名
password: "123456" #密码
logging: #打印日志
level:
org :
springframework:
data:
mongodb:
core: DEBUG
1、自定义MongoBaseRepository基础仓储接口继承MongoRepository,实现对MongoRepository的功能增强。MongoBaseRepository需要加上【@NoRepositoryBean】注解。
注意:需要继承MongoRepository接口,这样就能使用jpa原本以封装好的接口
@NoRepositoryBean
public interface MongoBaseRepository<T, ID> extends MongoRepository<T,ID>{
/**
* 将对象属性值作为条件进行删除,忽略id的值
* @param t 条件实体
*/
long deleteIgnoreId(T t);
.....更多方法
}
注意:实现类需要继承SimpleMongoRepository实现类,因为SimpleMongoRepository类是MongoRepository接口的实现类,当调用原本MongoRepository接口中已经实现的方法,会调用SimpleMongoRepository类中相对应的具体实现
public class MongoBaseRepositoryImpl<T, ID> extends SimpleMongoRepository<T, ID> implements MongoBaseRepository<T, ID> {
protected final MongoOperations mongoTemplate;
protected final MongoEntityInformation<T, ID> entityInformation;
private final String MONGO_ID_NAME = "_id";
private Class<T> clazz;
public MongoBaseRepositoryImpl(MongoEntityInformation<T, ID> metadata, MongoOperations mongoOperations) {
super(metadata, mongoOperations);
this.mongoTemplate = mongoOperations;
this.entityInformation = metadata;
clazz = entityInformation.getJavaType();
}
@Override
public long deleteIgnoreId(T t) {
//将id设为null
t = this.setIdNull(t);
mongoTemplate.remove(createCriteria(t,new ArrayList<>()),entityInformation.getCollectionName()).getDeletedCount();
return 1L;
}
......更多实现
}
@SpringBootApplication(exclude={ DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
@EnableMongoRepositories(repositoryBaseClass = MongoBaseRepositoryImpl.class)
public class SpringMongoDbApplication {
public static void main(String[] args) {
SpringApplication.run(SpringMongoDbApplication.class, args);
}
}
repositoryBaseClass = 自定义基础仓储接实现类
到这里就可以自己在自定义基础仓储接口中写一些自己的增删改查方法并在自定义基础仓储接实现类中实现这些方法,然后根据自己写的仓储类继承自定义基础仓储接口就可以使用了。
参考:https://blog.csdn.net/ChePQ/article/details/81072713
spring jpa官方地址:https://spring.io/projects/spring-data-jpa
spring data mongoDB官方地址:https://spring.io/projects/spring-data-mongodb
https://gitee.com/lp-li-ping/spring-mongo
将corn文件夹复制自己的文件夹下,就可以使用已经封装完的方法进行增删改查了
1、提供了更多的增删改查方法,更易用
2、实现一些用jpa自带的难以做到的查询,如类似与sql中的or和and查询
3、无需明白mongo的查询语法,复杂查询根据sql的查询方式构造查询条件
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@Document(value="tb_person")
public class User extends MongoEntity {
@Id
private Long id;
@Field("name")
private String name;
private Integer age;
private Address address;
private String hobby;
private String gender;
private String company;
private String phoneNum;
@Field("birth_day")
private Date birthDay;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class Address{
private String country;
private String city;
}
@Document(value=“tb_person”) mongo集合名为tb_person
@Id 指明id字段
@Field(“birth_day”) 指明字段名,当字段名和属性明不一致时可使用,不指明时字段名和属性名一致
@Repository
public interface UserRepository extends MongoBaseRepository<User,Long> {
}
MongoBaseRepository
序号 | 方法 | 含义 |
---|---|---|
1 | List |
查找所有 |
2 | List |
根据所有数据并根据排序规则排序,具体说明查看下面例子 |
3 | Page |
分页查询,可设置页码、排序等,具体说明查看下面例子 |
4 | 根据Example条件查询,具体说明查看下面例子 | |
5 | 根据Example条件查询并排序 | |
6 | 根据Example条件并分页 | |
7 | Iterable |
根据ID集合查询 |
8 | Optional |
根据id查询 |
9 | 根据Example条件查询一条,如有多条数据取第一条数据 | |
10 | 保存所有,会验证id,如果无id或不存在该id会新增,如存在此id会更新 | |
11 | 保存数据,会验证id,如果无id或不存在该id会新增,如存在此id会更新 | |
12 | 根据集合进行新增多条数据 | |
13 | 新增一条数据 | |
14 | void deleteAll(); | 删除所有数据 |
15 | void deleteAll(Iterable extends T> var1); | 根据集合删除所匹配的数据,是根据id进行匹配,无id报错 |
16 | void delete(T var1); | 根据实体删除所匹配的数据,是根据id进行匹配,无id报错 |
17 | void deleteById(ID var1); | 根据id删除 |
18 | boolean existsById(ID var1); | 根据id判断是否存在该记录 |
19 | 根据Example进行判断是否存在满足条件的记录 | |
20 | long count(); | 获取总记录数 |
21 | 根据Example条件获取符合条件的记录数 | |
22 | long update(T t); | 根据id进行更新,无id报错,会更新null值,具体说明查看下面例子 |
23 | long updateIgnoreNull(T t); | 根据id进行更新,无id报错,不更新null值,具体说明查看下面例子 |
24 | long updateBatch(Collection |
根据集合进行更新,集合中的每个实体必须包含id,根据实体id进行更新,会更新null值,具体说明查看下面例子 |
25 | long updateBatchIgnoreNull(Collection |
根据集合进行更新,集合中的每个实体必须包含id,根据实体id进行更新,不会更新null值,具体说明查看下面例子 |
26 | long updateBatch(T condition,T update); | 根据条件批量更新,condition为检索条件,update更新对象,会更新null值,具体说明查看下面例子 |
27 | long updateBatchIgnoreNull(T condition,T update); | 根据条件批量更新,condition为检索条件,update更新对象,不会更新null值,具体说明查看下面例子 |
28 | List |
根据条件查询,支持where自定义查询,具体说明查看下面例子 |
29 | Page |
根据条件查询,支持where自定义查询,支持分页,具体说明查看下面例子 |
30 | long deletePlus(T t); | 根据where条件查询并删除匹配的记录,具体说明查看下面例子 |
31 | long updatePlus(T t); | 根据where条件查询并修改匹配的记录,具体说明查看下面例子 |
说明:1-21为spring jpa已经封装好的,22-31为自己封装
@SpringBootTest
@RunWith(SpringRunner.class)
public class SpringMongoDbApplicationTests {
@Autowired
private UserRepository userRepository;
@Test
public void find(){
//根据所有数据并根据id升序
List<User> list = userRepository.findAll(Sort.by("id").ascending());
list.forEach(System.out::println);
}
/**
User(id=1, name=小明, age=25, address=Address(country=中国, city=天津), hobby=爱学习, gender=男, company=宇宙最强公司, phoneNum=18723888666, birthDay=null)
User(id=2, name=小红, age=28, address=Address(country=中国, city=北京), hobby=爱摸鱼, gender=女, company=宇宙最弱公司, phoneNum=18723888888, birthDay=null)
User(id=3, name=小李, age=10, address=Address(country=美国, city=加州), hobby=打球, gender=女, company=地球最强, phoneNum=18888888888, birthDay=null)
User(id=4, name=小王, age=10, address=Address(country=英国, city=伦敦), hobby=化学, gender=男, company=地球最弱, phoneNum=188888832328, birthDay=Sat Feb 25 13:07:16 CST 2023)
*/
了解更多关于Sort排序:https://blog.csdn.net/apple125414/article/details/102563969
@SpringBootTest
@RunWith(SpringRunner.class)
public class SpringMongoDbApplicationTests {
@Autowired
private UserRepository userRepository;
@Test
public void find(){
//分页查询,页可以设置排序规则
List<User> list = userRepository.findAll(PageRequest.of(1,2)).getContent();
list.forEach(System.out::println);
}
/**
User(id=3, name=小李, age=10, address=Address(country=美国, city=加州), hobby=打球, gender=女, company=地球最强, phoneNum=18888888888, birthDay=null)
User(id=4, name=小王, age=10, address=Address(country=英国, city=伦敦), hobby=化学, gender=男, company=地球最弱, phoneNum=188888832328, birthDay=Sat Feb 25 13:07:16 CST 2023)
*/
@SpringBootTest
@RunWith(SpringRunner.class)
public class SpringMongoDbApplicationTests {
@Autowired
private UserRepository userRepository;
@Test
public void find(){
//查询性别为女的记录
List<User> list = userRepository.findAll(Example.of(new User().setGender("女")));
list.forEach(System.out::println);
}
/**
User(id=2, name=小红, age=28, address=Address(country=中国, city=北京), hobby=爱摸鱼, gender=女, company=宇宙最弱公司, phoneNum=18723888888, birthDay=null)
User(id=3, name=小李, age=10, address=Address(country=美国, city=加州), hobby=打球, gender=女, company=地球最强, phoneNum=18888888888, birthDay=null)
*/
了解更多关于Example查询: https://blog.csdn.net/long476964/article/details/79677526
@SpringBootTest
@RunWith(SpringRunner.class)
public class SpringMongoDbApplicationTests {
@Autowired
private UserRepository userRepository;
@Test
public void update(){
//更新id为1的记录,属性有值的更新,无值设为null
userRepository.update(new User().setId(1L).setCompany("我是被更新的公司"));
}
@SpringBootTest
@RunWith(SpringRunner.class)
public class SpringMongoDbApplicationTests {
@Autowired
private UserRepository userRepository;
@Test
public void update(){
//更新id为1的记录,只更新属性有值的字段
userRepository.updateIgnoreNull(new User().setId(2L).setCompany("我是被更新的公司").setHobby("爱好被会更新"));
}
@SpringBootTest
@RunWith(SpringRunner.class)
public class SpringMongoDbApplicationTests {
@Autowired
private UserRepository userRepository;
@Test
public void updateBatch(){
//根据集合执行更新,会更新null值,将id为2的年龄设为777,其他字段设为null,将id为3的公司设为哈哈哈,其他字段设为null,
List<User> list = Arrays.asList(new User().setId(2L).setAge(777), new User().setId(3L).setCompany("哈哈哈"));
userRepository.updateBatch(list);
}
}
@SpringBootTest
@RunWith(SpringRunner.class)
public class SpringMongoDbApplicationTests {
@Autowired
private UserRepository userRepository;
@Test
public void updateBatchIgnoreNull(){
//根据集合执行更新,不会更新null值,将id为2的年龄设为777,其他字段不变,将id为3的公司设为哈哈哈,其他字段不变
List<User> list = Arrays.asList(new User().setId(2L).setAge(777), new User().setId(3L).setCompany("哈哈哈"));
userRepository.updateBatch(list);
}
}
@SpringBootTest
@RunWith(SpringRunner.class)
public class SpringMongoDbApplicationTests {
@Autowired
private UserRepository userRepository;
@Test
public void updateBatch1(){
//根据条件批量更新,condition为检索条件,update更新对象,会更新null值,
//将性别为女年龄都更新为18岁,其他字段更新为null
User condition = new User().setGender("女");
User update = new User().setAge(18);
userRepository.updateBatch(condition,update);
}
}
@SpringBootTest
@RunWith(SpringRunner.class)
public class SpringMongoDbApplicationTests {
@Autowired
private UserRepository userRepository;
@Test
public void updateBatchIgnoreNull1(){
//根据条件批量更新,condition为检索条件,update更新对象,不会更新null值,
//将性别为男年龄都更新为30岁,其他字段不更新
User condition = new User().setGender("男");
User update = new User().setAge(30);
userRepository.updateBatchIgnoreNull(condition,update);
}
}
注意:方法名为*Plus的支持自定义Where查询,其他方法不支持,实体类需继承MongoEntity,可以实现复杂的查询。
@SpringBootTest
@RunWith(SpringRunner.class)
public class SpringMongoDbApplicationTests {
@Autowired
private UserRepository userRepository;
@Test
public void findPlus1(){
//设置年龄为10
User user = new User().setAge(10);
/**
* 创建检索条件,field为对象属性名(无论有无@Field注解)
* 我们可以用sql的方式理解,条件为
* where hobby in ("爱学习","化学") and birthDay >= "1998-01-22" and age = 10;
*/
user.createQuery("hobby",QueryType.IN,Arrays.asList("爱学习","化学"))
.and("birthDay",QueryType.MORE_OR_EQUAL_THAN,DateUtil.parse("1998-01-22"));
List<User> list = userRepository.findPlus(user);
list.forEach(System.out::println);
}
}
/**
*结果:
*User(id=4, name=小王, age=10, address=Address(country=英国, city=伦敦), hobby=化学, gender=男, company=地球最弱, phoneNum=188888832328, birthDay=Tue Sep 12 00:00:00 CST 2000)
*/
@SpringBootTest
@RunWith(SpringRunner.class)
public class SpringMongoDbApplicationTests {
@Autowired
private UserRepository userRepository;
@Test
public void findPlus2(){
//设置年龄为10
User user = new User().setAge(10);
/**
* 如果不想将属性值作为条件创建检索条件为
* user.createQuery("hobby",QueryType.IN,Arrays.asList("爱学习","化学"))
* .and("birthDay",QueryType.MORE_OR_EQUAL_THAN,DateUtil.parse("1998-01-22"))
* .onlyQueryWhere();
* 加上onlyQueryWhere即可
*
* 条件为 where hobby in ("爱学习","化学") and birthDay >= "1998-01-22"
* 不会把 age = 10 加到条件中
*/
user.createQuery("hobby",QueryType.IN,Arrays.asList("爱学习","化学"))
.and("birthDay",QueryType.MORE_OR_EQUAL_THAN,DateUtil.parse("1998-01-22"))
.onlyQueryWhere();
List<User> list = userRepository.findPlus(user);
list.forEach(System.out::println);
}
}
/**
*结果:
*User(id=1, name=小明, age=25, address=Address(country=中国, city=天津), hobby=爱学习, gender=男, company=宇宙最强公司, phoneNum=18723888666, birthDay=Mon Sep 21 00:00:00 CST 1998)
*User(id=4, name=小王, age=10, address=Address(country=英国, city=伦敦), hobby=化学, gender=男, company=地球最弱, phoneNum=188888832328, birthDay=Tue Sep 12 00:00:00 CST 2000)
*/
@SpringBootTest
@RunWith(SpringRunner.class)
public class SpringMongoDbApplicationTests {
@Autowired
private UserRepository userRepository;
@Test
public void findPlus3(){
User user = new User().setAge(10).setName("小明");
/**
* andBracket表示 and(
* orBracket表示 or(
* endBracket表示 )
* 注意:开始括号需要和结束括号数量相等,如有一个 andBracket或 orBracket 就必须有一个endBracket
* 创建检索条件,field为对象属性名(无论有无@Field注解)
* 我们可以用sql的方式理解,条件为 where hobby in ("爱学习","化学","打球") and (company = "地球最弱" or name = "小李") and age = 10;
* 为什么没有将属性name = "小明"条件?
* 这是因为检索条件以createQuery为准,如createQuery中出现了("name",QueryType.EQUAL,"小李")
* 条件就不会将属性 name = "小明"加入条件中
*/
user.createQuery("hobby",QueryType.IN,Arrays.asList("爱学习","化学","打球"))
.andBracket("company",QueryType.EQUAL,"地球最弱")
.or("name",QueryType.EQUAL,"小李")
.endBracket();
List<User> list = userRepository.findPlus(user);
list.forEach(System.out::println);
}
}
/**
*结果:
*User(id=3, name=小李, age=10, address=Address(country=美国, city=加州), hobby=打球, gender=女, company=地球最强, phoneNum=18888888888, birthDay=Tue Sep 21 00:00:00 CST 1993)
*User(id=4, name=小王, age=10, address=Address(country=英国, city=伦敦), hobby=化学, gender=男, company=地球最弱, phoneNum=188888832328, birthDay=Tue Sep 12 00:00:00 CST 2000)
*/
@SpringBootTest
@RunWith(SpringRunner.class)
public class SpringMongoDbApplicationTests {
@Autowired
private UserRepository userRepository;
@Test
public void findPlus4(){
User user = new User().setAge(10).setName("小明");
/**
* 创建检索条件: where hobby in ("爱学习","化学","打球") and gender = "男" or address.country = 中国 and name = "小孙"
* 其中有两点需注意:
* 1、User是个复杂对象,里面含有Address属性,Address对象里有country 和 city属性,
* 当我们想检索country为中国的,条件为 属性名.属性对象属性名
* 如:address.country address为user对象中的属性名,country为Address对象属性名
* 2、当有or时需要注意优先级,优先级与sql中的and和or优先级一致,and优先级大于or优先级
* 所以该检索条件中
* hobby in ("爱学习","化学","打球") and gender = "男"是一个整体,
* address.country = 中国 and name = "小孙"是一个整体
* 两个整体间用or连接
*/
user.createQuery("hobby",QueryType.IN,Arrays.asList("爱学习","化学","打球"))
.and("gender",QueryType.EQUAL,"男")
.or("address.country",QueryType.EQUAL,"中国")
.and("name",QueryType.EQUAL,"小孙")
.onlyQueryWhere();
List<User> list = userRepository.findPlus(user);
list.forEach(System.out::println);
}
}
/**
*结果:
*User(id=1, name=小明, age=25, address=Address(country=中国, city=天津), hobby=爱学习, gender=男, company=宇宙最强公司, phoneNum=18723888666, birthDay=Mon Sep 21 00:00:00 CST 1998)
*User(id=4, name=小王, age=10, address=Address(country=英国, city=伦敦), hobby=化学, gender=男, company=地球最弱, phoneNum=188888832328, birthDay=Tue Sep 12 00:00:00 CST 2000)
*User(id=5, name=小孙, age=12, address=Address(country=中国, city=重庆), hobby=数学, gender=男, company=地球最弱, phoneNum=188888842328, birthDay=Mon Sep 21 00:00:00 CST 1998)
*/
@SpringBootTest
@RunWith(SpringRunner.class)
public class SpringMongoDbApplicationTests {
@Autowired
private UserRepository userRepository;
@Test
public void findPlusPage(){
User user = new User();
user.createQuery("gender",QueryType.EQUAL,"男");
//1页两条数据
Page<User> page = userRepository.findPlus(user, PageRequest.of(1, 2));
page.getContent().forEach(System.out::println);
}
}
/**
*结果:
*User(id=1, name=小明, age=25, address=Address(country=中国, city=天津), hobby=爱学习, gender=男, company=宇宙最强公司, phoneNum=18723888666, birthDay=Mon Sep 21 00:00:00 CST 1998)
*User(id=4, name=小王, age=10, address=Address(country=英国, city=伦敦), hobby=化学, gender=男, company=地球最弱, phoneNum=188888832328, birthDay=Tue Sep 12 00:00:00 CST 2000)
*/
@SpringBootTest
@RunWith(SpringRunner.class)
public class SpringMongoDbApplicationTests {
@Autowired
private UserRepository userRepository;
@Test
public void deletePlus(){
User user = new User();
//删除性别男且名字为小明的记录
user.createQuery("gender",QueryType.EQUAL,"男").and("name",QueryType.EQUAL,"小明");
userRepository.findPlus(user);
}
}
@SpringBootTest
@RunWith(SpringRunner.class)
public class SpringMongoDbApplicationTests {
@Autowired
private UserRepository userRepository;
@Test
public void updatePlus1(){
User user = new User().setAge(18).setCompany("火星公司");
//查询性别为男address.country为中国的记录并将符合条件的记录age更新18,company更新为火星公司,其他字段不更新
user.createQuery("gender",QueryType.EQUAL,"男")
.and("address.country",QueryType.EQUAL,"中国");
userRepository.updatePlus(user);
}
}
@SpringBootTest
@RunWith(SpringRunner.class)
public class SpringMongoDbApplicationTests {
@Autowired
private UserRepository userRepository;
@Test
public void updatePlus2(){
User user = new User().setAge(18).setCompany("火星公司");
/**
* 查询性别为男address.country为中国的记录并将符合条件的记录年龄更新18,
* 公司更新为火星公司,并将其他字段更新为null
* 只需在createQuery条件上加上updateNullValue()即可
*/
user.createQuery("gender",QueryType.EQUAL,"男")
.and("address.country",QueryType.EQUAL,"中国")
.updateNullValue();
userRepository.updatePlus(user);
}
}
由于集成了spring jpa,我们也可以根据spring定义的方式取定义方法,如UserRepository接口中新增findByAge方法,不需要去实现该方法,但是对方法命名有约束
@Repository
public interface UserRepository extends MongoBaseRepository<User,Long> {
List<User> findByAge(Integer age);
}
测试
@SpringBootTest
@RunWith(SpringRunner.class)
public class SpringMongoDbApplicationTests {
@Autowired
private UserRepository userRepository;
@Test
public void findByAge(){
List<User> list = userRepository.findByAge(10);
list.forEach(System.out::println);
}
}
/**
* 结果:
*User(id=3, name=小李, age=10, address=Address(country=美国, city=加州), hobby=打球, gender=女, company=地球最强, phoneNum=18888888888, birthDay=Tue Sep 21 00:00:00 CST 1993)
*User(id=4, name=小王, age=10, address=Address(country=英国, city=伦敦), hobby=化学, gender=男, company=地球最弱, phoneNum=188888832328, birthDay=Tue Sep 12 00:00:00 CST 2000)
*/
参考:https://blog.csdn.net/java_zyq/article/details/85262373
第一次尝试封装,做得不好,以后会更加努力,希望对大家所有帮助,有疑问可以在评论区讨论,一起进步,也希望大家能点点赞。