SpringDataJPA中List<对象>类型的属性,怎么根据子对象中的属性值查询父类对象,如果父类有同名的属性如何进行查询(通过findBy方式)
一半黑是还有骨,十分红处变成灰。十分能耐使七分,留下三分给儿孙。十分能耐都使尽,后辈儿孙不如人
用了好久的JPA今天终于知道如何通过子对象的属性查询父类对象了,实体类属性
数据库数据如下:
{
"_id" : ObjectId("5c37f8756600ca1c680b3a80"),
"journalId" : "5c36e22c13f6b34064283d5e",
"dataSetId" : "533223368594292736",
"clicks" : NumberLong(78),
"collects" : NumberLong(0),
"downloads" : NumberLong(0),
"points" : 0.0,
"pointCount" : NumberInt(0),
"refs" : NumberLong(0),
"papers" : [
{
"title" : "中国27省乡镇(街道)级人口密度数据集(2000年)",
"titleEn" : "A dataset of population density at township level for 27 provinces of China (2000)",
"url" : "http://www.csdata.org/p/7/15/"
}
],
"source" : "中国科学数据",
"title" : "中国27省乡镇(街道)级人口密度数据集(2000年)",
"author" : "柏中强;王卷乐",
"taxonomy" : "地球科学",
"keyword" : "人口分布;密度;乡镇;中国",
"introduction" : "人口密度是表现人口分布最主要的形式和衡量人口分布地区差异的主要指标。乡镇(街道)处于我国行政体系的基层位置,也是中国人口普查数据公开发布的最小行政单元,乡镇级人口密度数据能够客观、精细地表征中国人口分布的空间格局和态势,对于资源、环境及人口问题的研究具有十分重要的意义。本文规范化处理了中国辽宁、吉林、内蒙古(部分地区)、北京、天津、上海、河北、河南、陕西、宁夏、山西、山东、安徽、江苏、湖南、湖北、江西、浙江、福建、广东、海南、云南、贵州、青海、西藏等25个省(直辖市、自治区)乡镇(街道)级行政界线数据及第五次人口普查乡镇(街道)级人口统计数据,保证乡镇边界和县(区)界一致、各乡镇单元空间范围和人口普查信息一一对应。在此基础上,准确地匹配了各乡镇的空间范围及人口普查信息,计算了各乡镇的平均人口密度,形成了本数据集。",
"reference" : "柏中强,王卷乐(2015)中国27省乡镇(街道)级人口密度数据集(2000年).Science Data Bank.http://www.dx.doi.org/10.11922/sciencedb.2",
"referenceLink" : "",
"doi" : "10.11922/sciencedb.2",
"pid" : "21.86101/sciencedb.2",
"username" : "[email protected]",
"version" : "V1",
"status" : "3",
"updateDate" : ISODate("2015-07-16T00:36:45.000+0000"),
"publishDate" : ISODate("2015-07-16T00:36:45.000+0000"),
"count" : NumberInt(0),
"record" : NumberInt(0),
"coverUrl" : "/cover/journal/533223368594292736.jpg",
"language" : "zh_CN",
"papersUrl" : "www.baidu.com",
"_class" : "cn.sciencedb.common.domain.mongo.JournalDataSetZh"
}
@Getter
@Setter
@Document(collection = "journal_dataset_zh")
public class JournalDataSetZh extends DataSet implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private String id;
private String journalId; // journalId
private String dataSetId; // dataSetId
private long clicks; // 点击数
private long collects; // 收藏
private long downloads; // 下载
private double points; // 评分
private int pointCount; // 评分人数
private long refs; // 数据引用文件下载数
private List papers;// 关联论文
private String source;// 数据来源
private List files;// 文件地址
private String papersUrl;
}
@Setter
@Getter
@ToString
public class Paper implements Serializable {
private static final long serialVersionUID = 1L;
private String title;// 论文中文标题
private String titleEn;// 论文英文标题
private String doi;// 论文DOI
private String url;// 论文链接
}
通过上面两个实体可以看出 JournalDataSetZh 表中有一个List
类型的papers属性,还要一个String类型的papersUrl的属性,这个属性是为了测试重名属性存在的情况。
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class SdbJournalServiceApplicationTest {
@Autowired
private JournalZhRepository journalZhRepository;
@Test
public void test(){
List list = journalZhRepository.findByPapers_Url("http://www.csdata.org/p/7/15/");
List list1 = journalZhRepository.findByPapersUrl("www.baidu.com");
for(JournalDataSetZh journal : list){
System.out.println("******************************" + journal.toString());
}
for(JournalDataSetZh journal : list1){
System.out.println("+++++++++++++++++++++++++++++++" + journal.toString());
}
}
}
运行结果如下:
******************************cn.sciencedb.common.domain.mongo.JournalDataSetZh@19a2b224[id=5c37f8756600ca1c680b3a80,journalId=5c36e22c13f6b34064283d5e,dataSetId=533223368594292736,clicks=78,collects=0,downloads=0,points=0.0,pointCount=0,refs=0,papers=[Paper(title=中国27省乡镇(街道)级人口密度数据集(2000年), titleEn=A dataset of population density at township level for 27 provinces of China (2000), doi=null, url=http://www.csdata.org/p/7/15/)],source=中国科学数据,files=,papersUrl=www.baidu.com,title=中国27省乡镇(街道)级人口密度数据集(2000年),author=柏中强;王卷乐,taxonomy=地球科学,keyword=人口分布;密度;乡镇;中国,introduction=人口密度是表现人口分布最主要的形式和衡量人口分布地区差异的主要指标。乡镇(街道)处于我国行政体系的基层位置,也是中国人口普查数据公开发布的最小行政单元,乡镇级人口密度数据能够客观、精细地表征中国人口分布的空间格局和态势,对于资源、环境及人口问题的研究具有十分重要的意义。本文规范化处理了中国辽宁、吉林、内蒙古(部分地区)、北京、天津、上海、河北、河南、陕西、宁夏、山西、山东、安徽、江苏、湖南、湖北、江西、浙江、福建、广东、海南、云南、贵州、青海、西藏等25个省(直辖市、自治区)乡镇(街道)级行政界线数据及第五次人口普查乡镇(街道)级人口统计数据,保证乡镇边界和县(区)界一致、各乡镇单元空间范围和人口普查信息一一对应。在此基础上,准确地匹配了各乡镇的空间范围及人口普查信息,计算了各乡镇的平均人口密度,形成了本数据集。,funding=,reference=柏中强,王卷乐(2015)中国27省乡镇(街道)级人口密度数据集(2000年).Science Data Bank.http://www.dx.doi.org/10.11922/sciencedb.2,referenceLink=,copyright=,fileType=,doi=10.11922/sciencedb.2,pid=21.86101/sciencedb.2,[email protected],version=V1,status=3,updateDate=Thu Jul 16 08:36:45 CST 2015,publishDate=Thu Jul 16 08:36:45 CST 2015,size=,count=0,record=0,shortUrl=,accessStatus=,coverUrl=/cover/journal/533223368594292736.jpg,language=zh_CN,extMetadata=,authors=]
+++++++++++++++++++++++++++++++cn.sciencedb.common.domain.mongo.JournalDataSetZh@43d00636[id=5c37f8756600ca1c680b3a80,journalId=5c36e22c13f6b34064283d5e,dataSetId=533223368594292736,clicks=78,collects=0,downloads=0,points=0.0,pointCount=0,refs=0,papers=[Paper(title=中国27省乡镇(街道)级人口密度数据集(2000年), titleEn=A dataset of population density at township level for 27 provinces of China (2000), doi=null, url=http://www.csdata.org/p/7/15/)],source=中国科学数据,files=,papersUrl=www.baidu.com,title=中国27省乡镇(街道)级人口密度数据集(2000年),author=柏中强;王卷乐,taxonomy=地球科学,keyword=人口分布;密度;乡镇;中国,introduction=人口密度是表现人口分布最主要的形式和衡量人口分布地区差异的主要指标。乡镇(街道)处于我国行政体系的基层位置,也是中国人口普查数据公开发布的最小行政单元,乡镇级人口密度数据能够客观、精细地表征中国人口分布的空间格局和态势,对于资源、环境及人口问题的研究具有十分重要的意义。本文规范化处理了中国辽宁、吉林、内蒙古(部分地区)、北京、天津、上海、河北、河南、陕西、宁夏、山西、山东、安徽、江苏、湖南、湖北、江西、浙江、福建、广东、海南、云南、贵州、青海、西藏等25个省(直辖市、自治区)乡镇(街道)级行政界线数据及第五次人口普查乡镇(街道)级人口统计数据,保证乡镇边界和县(区)界一致、各乡镇单元空间范围和人口普查信息一一对应。在此基础上,准确地匹配了各乡镇的空间范围及人口普查信息,计算了各乡镇的平均人口密度,形成了本数据集。,funding=,reference=柏中强,王卷乐(2015)中国27省乡镇(街道)级人口密度数据集(2000年).Science Data Bank.http://www.dx.doi.org/10.11922/sciencedb.2,referenceLink=,copyright=,fileType=,doi=10.11922/sciencedb.2,pid=21.86101/sciencedb.2,[email protected],version=V1,status=3,updateDate=Thu Jul 16 08:36:45 CST 2015,publishDate=Thu Jul 16 08:36:45 CST 2015,size=,count=0,record=0,shortUrl=,accessStatus=,coverUrl=/cover/journal/533223368594292736.jpg,language=zh_CN,extMetadata=,authors=]
List
list = journalZhRepository.findByPapers_Url("http://www.csdata.org/p/7/15/");
这个方法是通过 journal 表中Papers属性中子类(Paper类)中的Url属性,查询符合条件的所有 journal 数据。
Listlist1 = journalZhRepository.findByPapersUrl("www.baidu.com");
这个方法是通过 journal 表中 papersUrl 属性的值直接查询 符合条件的 journal 数据。
SpringDataJPA中常用的查询(findBy方式)
首先参照官方文档创建指定数据库
CREATE TABLE `demo_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;
示例代码及注释<参照以上顺序>
/**
* @Author: EvilSay
* @Date: 2019/2/25 16:15
*/
public interface DemoJpaRepositories extends JpaRepository {
//根据firstName与LastName查找(两者必须在数据库有)
DemoJpa findByFirstNameAndLastName(String firstName, String lastName);
//根据firstName或LastName查找(两者其一有就行)
DemoJpa findByLastNameOrFirstName(String lastName,String firstName);
//根据firstName查找它是否存在数据库里<类似与以下关键字>
//DemoJpa findByFirstName(String firstName);
DemoJpa findByFirstNameIs(String firstName);
//在Age数值age到age2之间的数据
List findByAgeBetween(Integer age, Integer age2);
//小于指定age数值之间的数据
List findByAgeLessThan(Integer age);
//小于等于指定age数值的数据
List findByAgeLessThanEqual(Integer age);
//大于指定age数值之间的数据
List findByAgeGreaterThan(Integer age);
//大于或等于指定age数值之间的数据
List findByAgeGreaterThanEqual(Integer age);
//在指定age数值之前的数据类似关键字
List findByAgeAfter(Integer age);
//在指定age数值之后的数据类似关键字
List findByAgeBefore(Integer age);
//返回age字段为空的数据
List findByAgeIsNull();
//返回age字段不为空的数据
List findByAgeNotNull();
/**
* 该关键字我一度以为是类似数据库的模糊查询,
* 但是我去官方文档看到它里面并没有通配符。
* 所以我觉得它类似
* DemoJpa findByFirstName(String firstName);
* @see https://docs.spring.io/spring-data/jpa/docs/2.1.5.RELEASE/reference/html/#jpa.repositories
*/
DemoJpa findByFirstNameLike(String firstName);
//同上
List findByFirstNameNotLike(String firstName);
//查找数据库中指定类似的名字(如:输入一个名字"M" Jpa会返回多个包含M开头的名字的数据源)<类似数据库模糊查询>
List findByFirstNameStartingWith(String firstName);
//查找数据库中指定不类似的名字(同上)
List findByFirstNameEndingWith(String firstName);
//查找包含的指定数据源(这个与以上两个字段不同的地方在与它必须输入完整的数据才可以查询)
List findByFirstNameContaining(String firstName);
//根据age选取所有的数据源并按照LastName进行升序排序
List findByAgeOrderByLastName(Integer age);
//返回不是指定age的所有数据
List findByAgeNot(Integer age);
//查找包含多个指定age返回的数据
List findByAgeIn(List age);
}
单元测试<已经全部通过>
@SpringBootTest
@RunWith(SpringRunner.class)
@Slf4j
public class DemoJpaRepositoriesTest {
@Autowired
private DemoJpaRepositories repositories;
@Test
public void findByFirstNameAndLastName() {
DemoJpa demoJpa = repositories.findByFirstNameAndLastName("May", "Eden");
Assert.assertEquals(demoJpa.getFirstName(),"May");
}
@Test
public void findByLastNameOrFirstName() {
DemoJpa demoJpa = repositories.findByLastNameOrFirstName("Geordie", "Eden");
Assert.assertNotEquals(demoJpa.getLastName(),"Eden");
}
@Test
public void findByFirstNameIs() {
DemoJpa demoJpa = repositories.findByFirstNameIs("amy");
Assert.assertNull(demoJpa);
}
@Test
public void findByAgeBetween() {
List demoJpaList = repositories.findByAgeBetween(15, 17);
Assert.assertEquals(3,demoJpaList.size());
}
@Test
public void findByAgeLessThan() {
List demoJpaList = repositories.findByAgeLessThan(17);
Assert.assertEquals(2,demoJpaList.size());
}
@Test
public void findByAgeLessThanEqual() {
List demoJpaList = repositories.findByAgeLessThanEqual(17);
Assert.assertEquals(3,demoJpaList.size());
}
@Test
public void findByAgeGreaterThan() {
List demoJpaList = repositories.findByAgeGreaterThan(17);
Assert.assertEquals(2,demoJpaList.size());
}
@Test
public void findByAgeGreaterThanEqual() {
List demoJpaList = repositories.findByAgeGreaterThanEqual(17);
Assert.assertEquals(3,demoJpaList.size());
}
@Test
public void findByAgeAfter() {
List demoJpaList = repositories.findByAgeAfter(17);
Assert.assertEquals(2,demoJpaList.size());
}
@Test
public void findByAgeBefore() {
List demoJpaList = repositories.findByAgeBefore(17);
Assert.assertEquals(2,demoJpaList.size());
}
@Test
public void findByAgeIsNull() {
List demoJpaList = repositories.findByAgeIsNull();
Assert.assertEquals(0,demoJpaList.size());
}
@Test
public void findByAgeNotNull() {
List demoJpaList = repositories.findByAgeNotNull();
Assert.assertEquals(5,demoJpaList.size());
}
@Test
public void findByFirstNameLike() {
DemoJpa demoJpa = repositories.findByFirstNameLike("May");
Assert.assertNotNull(demoJpa);
}
@Test
public void findByFirstNameNotLike() {
}
@Test
public void findByFirstNameStartingWith() {
List demoJpaList = repositories.findByFirstNameStartingWith("May");
Assert.assertEquals(2,demoJpaList.size());
}
@Test
public void findByFirstNameEndingWith() {
List demoJpaList = repositories.findByFirstNameEndingWith("Evil");
Assert.assertEquals(0,demoJpaList.size());
}
@Test
public void findByFirstNameContaining() {
List demoJpaList = repositories.findByFirstNameContaining("hack");
Assert.assertEquals(0,demoJpaList.size());
}
@Test
public void findByAgeOrderByLastName() {
List demoJpaList = repositories.findByAgeOrderByLastName(18);
for (DemoJpa demoJpaL : demoJpaList){
log.info("数据结果"+demoJpaL.toString());
}
}
@Test
public void findByAgeNot() {
List demoJpaList = repositories.findByAgeNot(20);
Assert.assertEquals(5,demoJpaList.size());
}
@Test
public void findByAgeIn() {
List demoJpaList = repositories.findByAgeIn(Arrays.asList(15, 16));
Assert.assertEquals(2,demoJpaList.size());
}
}