Java 弹簧&x27;当使用findAll或findById时,s crudepository会对对象进行不同的组装
我使用Spring的Crudepository来持久化一个对象(WorkingDays),它包含一个其他对象的列表(Filter),基本上包含一组枚举。 使用Crudepository的findAll函数时,对象按预期进行组装;使用findById函数时,返回的WorkingDays对象包含错误的筛选项列表 请参见下面的示例Java 弹簧&x27;当使用findAll或findById时,s crudepository会对对象进行不同的组装,java,spring,hibernate,spring-data-jpa,jpa-2.0,Java,Spring,Hibernate,Spring Data Jpa,Jpa 2.0,我使用Spring的Crudepository来持久化一个对象(WorkingDays),它包含一个其他对象的列表(Filter),基本上包含一组枚举。 使用Crudepository的findAll函数时,对象按预期进行组装;使用findById函数时,返回的WorkingDays对象包含错误的筛选项列表 请参见下面的示例 package com.example.jpastackoverflow.model; import lombok.Data; import javax.persisten
package com.example.jpastackoverflow.model;
import lombok.Data;
import javax.persistence.*;
import java.util.List;
@Entity
@Table(name = "working_days")
@Data
public class WorkingDays {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String someFiled;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "working_days_id")
private List<Filter> filterList;
}
package com.example.jpastackoverflow.model;
导入org.springframework.data.repository.crudepository;
导入org.springframework.stereotype.Repository;
导入javax.transaction.Transactional;
@存储库(“存储库”)
@交易的
公共接口Repo扩展了crudepository{}
最后是测试:
@SpringBootTest
class WorkingDaysTest {
@Autowired
private Repo repo;
@BeforeEach
void setUp() {
Set<DAYS> days1 = new HashSet<>();
Set<DAYS> days2 = new HashSet<>();
days1.add(DAYS.MONDAY);
days1.add(DAYS.TUESDAY);
days1.add(DAYS.WEDNESDAY);
days2.add(DAYS.THURSDAY);
days2.add(DAYS.FRIDAY);
days2.add(DAYS.SATURDAY);
days2.add(DAYS.SUNDAY);
Filter filter1 = new Filter();
Filter filter2 = new Filter();
filter1.setSomeFiled("foo");
filter2.setSomeFiled("bar");
filter1.setDays(days1);
filter2.setDays(days2);
List<Filter> filterList = new ArrayList<>();
filterList.add(filter1); //just add one entry to the list (Mon, Tue, Wed)
filterList.add(filter2); //just add one entry to the list (Thu, Fri, Sat, Sun)
WorkingDays workingDays1 = new WorkingDays();
workingDays1.setSomeFiled("foo1");
workingDays1.setFilterList(filterList);
repo.save(workingDays1);
}
@Test
void findAll() {
Iterable<WorkingDays> it = repo.findAll();
it.forEach(wd -> System.out.println(wd.toString()));
/*
WorkingDays(id=1,
someFiled=foo1,
filterList=[
Filter(id=1, someFiled=foo, days=[TUESDAY, MONDAY, WEDNESDAY]),
Filter(id=2, someFiled=bar, days=[SUNDAY, THURSDAY, FRIDAY, SATURDAY])])
*/
}
@Test
void findById() {
Optional<WorkingDays> oWorkingDays1 = repo.findById(1L);
assertTrue(oWorkingDays1.isPresent());
System.out.println(oWorkingDays1.get().toString());
/*
WorkingDays(id=1,
someFiled=foo1,
filterList=[
Filter(id=1, someFiled=foo, days=[MONDAY, TUESDAY, WEDNESDAY]),
Filter(id=1, someFiled=foo, days=[MONDAY, TUESDAY, WEDNESDAY]),
Filter(id=1, someFiled=foo, days=[MONDAY, TUESDAY, WEDNESDAY]),
Filter(id=2, someFiled=bar, days=[SATURDAY, SUNDAY, THURSDAY, FRIDAY]),
Filter(id=2, someFiled=bar, days=[SATURDAY, SUNDAY, THURSDAY, FRIDAY]),
Filter(id=2, someFiled=bar, days=[SATURDAY, SUNDAY, THURSDAY, FRIDAY]),
Filter(id=2, someFiled=bar, days=[SATURDAY, SUNDAY, THURSDAY, FRIDAY])])
*/
}
}
@SpringBootTest
类工作日测试{
@自动连线
私人回购;
@之前
无效设置(){
Set days1=新的HashSet();
Set days2=新的HashSet();
days1.添加(DAYS.周一);
days1.add(天,星期二);
天1.添加(天,星期三);
days2.add(天,星期四);
days2.add(天,星期五);
days2.add(天,星期六);
days2.add(DAYS.SUNDAY);
过滤器过滤器1=新过滤器();
过滤器过滤器2=新过滤器();
过滤器1.设置文件(“foo”);
过滤器2.设置文件(“bar”);
过滤器1.设置天数(第1天);
过滤器2.设置天数(第2天);
List filterList=new ArrayList();
filterList.add(filter1);//只需在列表中添加一个条目(周一、周二、周三)
filterList.add(filter2);//只需在列表中添加一个条目(周四、周五、周六、周日)
工作日工作日1=新工作日();
工作日1.设置文件(“foo1”);
工作日1.设置过滤器列表(过滤器列表);
回购保存(工作日1);
}
@试验
void findAll(){
Iterable it=repo.findAll();
it.forEach(wd->System.out.println(wd.toString());
/*
工作日(id=1,
somefield=foo1,
过滤列表=[
过滤器(id=1,somefield=foo,days=[周二、周一、周三],
过滤器(id=2,somefield=bar,days=[星期日、星期四、星期五、星期六])
*/
}
@试验
void findById(){
可选oWorkingDays1=回购findById(1L);
assertTrue(oWorkingDays1.isPresent());
System.out.println(oWorkingDays1.get().toString());
/*
工作日(id=1,
somefield=foo1,
过滤列表=[
过滤器(id=1,somefield=foo,days=[周一、周二、周三],
过滤器(id=1,somefield=foo,days=[周一、周二、周三],
过滤器(id=1,somefield=foo,days=[周一、周二、周三],
过滤器(id=2,somefield=bar,days=[周六、周日、周四、周五],
过滤器(id=2,somefield=bar,days=[周六、周日、周四、周五],
过滤器(id=2,somefield=bar,days=[周六、周日、周四、周五],
过滤器(id=2,somefield=bar,days=[周六、周日、周四、周五])
*/
}
}
findAll在存储时使用带有两个条目的“filterList”组合工作日(参见测试用例中的注释)
findById用一个包含七个条目的“filterList”组合工作日。对于“天”集合中的每个条目,似乎都会创建一个新的“过滤器”对象并将其添加到“过滤器列表”(请参见测试用例中的注释)
有人能解释一下为什么会发生这种情况,并提出一个可行的解决方案吗?这就是你在一个袋子里找到加入协会的机会。使用
设置过滤器列表代码>而不是列表过滤器列表代码>以避免这种情况。您能再解释一下吗?为什么它对findAll有效,而对findById无效?我认为原因是findAll
使用了一个查询,该查询不进行fetch连接,从而导致基数增加,而findById
使用select fetching(发出单独的select语句)来初始化关联,它保留了基数。我想知道有没有办法用列表来解决它?我需要一个列表,以防我想添加两次相同的过滤器,所以应该有可能吗?如果你想使用一个没有顺序索引的列表,你需要使用选择抓取(@Fetch(FetchMode.select)
),除非你指定一个合适的@BatchSize
package com.example.jpastackoverflow.model;
public enum DAYS {
MONDAY(0),
TUESDAY(1),
WEDNESDAY(2),
THURSDAY(3),
FRIDAY(4),
SATURDAY(5),
SUNDAY(6);
private final Integer day;
DAYS(final Integer day) {
this.day = day;
}
public final Integer getDay() {
return day;
}
}
package com.example.jpastackoverflow.model;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import javax.transaction.Transactional;
@Repository("Repository")
@Transactional
public interface Repo extends CrudRepository<WorkingDays, Long> {}
@SpringBootTest
class WorkingDaysTest {
@Autowired
private Repo repo;
@BeforeEach
void setUp() {
Set<DAYS> days1 = new HashSet<>();
Set<DAYS> days2 = new HashSet<>();
days1.add(DAYS.MONDAY);
days1.add(DAYS.TUESDAY);
days1.add(DAYS.WEDNESDAY);
days2.add(DAYS.THURSDAY);
days2.add(DAYS.FRIDAY);
days2.add(DAYS.SATURDAY);
days2.add(DAYS.SUNDAY);
Filter filter1 = new Filter();
Filter filter2 = new Filter();
filter1.setSomeFiled("foo");
filter2.setSomeFiled("bar");
filter1.setDays(days1);
filter2.setDays(days2);
List<Filter> filterList = new ArrayList<>();
filterList.add(filter1); //just add one entry to the list (Mon, Tue, Wed)
filterList.add(filter2); //just add one entry to the list (Thu, Fri, Sat, Sun)
WorkingDays workingDays1 = new WorkingDays();
workingDays1.setSomeFiled("foo1");
workingDays1.setFilterList(filterList);
repo.save(workingDays1);
}
@Test
void findAll() {
Iterable<WorkingDays> it = repo.findAll();
it.forEach(wd -> System.out.println(wd.toString()));
/*
WorkingDays(id=1,
someFiled=foo1,
filterList=[
Filter(id=1, someFiled=foo, days=[TUESDAY, MONDAY, WEDNESDAY]),
Filter(id=2, someFiled=bar, days=[SUNDAY, THURSDAY, FRIDAY, SATURDAY])])
*/
}
@Test
void findById() {
Optional<WorkingDays> oWorkingDays1 = repo.findById(1L);
assertTrue(oWorkingDays1.isPresent());
System.out.println(oWorkingDays1.get().toString());
/*
WorkingDays(id=1,
someFiled=foo1,
filterList=[
Filter(id=1, someFiled=foo, days=[MONDAY, TUESDAY, WEDNESDAY]),
Filter(id=1, someFiled=foo, days=[MONDAY, TUESDAY, WEDNESDAY]),
Filter(id=1, someFiled=foo, days=[MONDAY, TUESDAY, WEDNESDAY]),
Filter(id=2, someFiled=bar, days=[SATURDAY, SUNDAY, THURSDAY, FRIDAY]),
Filter(id=2, someFiled=bar, days=[SATURDAY, SUNDAY, THURSDAY, FRIDAY]),
Filter(id=2, someFiled=bar, days=[SATURDAY, SUNDAY, THURSDAY, FRIDAY]),
Filter(id=2, someFiled=bar, days=[SATURDAY, SUNDAY, THURSDAY, FRIDAY])])
*/
}
}