spring的crudepository会对对象进行不同的组装

mefy6pfw  于 2021-07-13  发布在  Java
关注(0)|答案(1)|浏览(342)

我使用spring的crudepository来持久化一个对象(workingdays),它包含一个其他对象的列表(filter),基本上包含一组枚举。使用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,
        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])])
         */
    }
}

findall用一个带有两个条目的“filterlist”来组装workingdays,就像它存储时一样(参见测试用例中的注解)。
findbyid用一个包含7个条目的“filterlist”来组装工作日。对于“days”集合中的每个条目,都会创建一个新的“filter”对象并将其添加到“filterslist”中(请参见测试用例中的注解)。
有人能解释为什么会发生这种情况并提出一个有效的解决方案吗?

gmxoilav

gmxoilav1#

这就是当你在一个袋子里找人加入一个社团时得到的。使用 Set<Filter> filterList; 而不是 List<Filter> filterList; 为了避免这种情况。

相关问题