如何解决Spring 的 CrudRepository 在使用 findAll 或 findById 时以不同的方式组装对象
我正在使用 Spring 的 CrudRepository 来持久化一个对象 (WorkingDays),该对象包含一个其他对象列表 (Filter),它基本上包含一组 Enum。 当使用 CrudRepository 的 findAll 函数时,对象按预期组装,当使用 findById 函数时,返回的 WorkingDays 对象包含错误的过滤项目列表
看下面的最小例子
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;
import lombok.Data;
import javax.persistence.*;
import java.util.Set;
@Entity
@Table(name = "filter")
@Data
public class Filter {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String someFiled;
@ElementCollection(targetClass = DAYS.class,fetch = FetchType.EAGER)
@CollectionTable(name = "filter_days",joinColumns = @JoinColumn(name = "filter_id"))
@Column(name = "days")
@Enumerated(EnumType.STRING)
private Set<DAYS> days = null;
}
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,days=[MONDAY,TUESDAY,Filter(id=1,days=[SATURDAY,SUNDAY,FRIDAY]),FRIDAY])])
*/
}
}
findAll 使用带有两个条目的“filterList”组装工作日,因为它被存储(参见测试用例中的注释)。
findById 将 WorkingDays 与包含七个条目的“filterList”组合在一起。看起来对于 'days' 集合中的每个条目,都会创建一个新的 'Filter' 对象并将其添加到 'filtersList'(请参阅测试用例中的注释)。
谁能解释为什么会发生这种情况并提出可行的解决方案?
解决方法
这就是当你在一个包中加入一个协会时你得到的。使用 Set<Filter> filterList;
而不是 List<Filter> filterList;
来避免这种情况。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。