这是一个简化的工作代码。有一个映射的超类和两个子类(在现实生活中,超类当然包含更多的字段)
Animal.java
@MappedSuperclass
@lombok.NoArgsConstructor
@lombok.RequiredArgsConstructor
public abstract class Animal {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@lombok.Getter
private Long id;
@lombok.Getter
@lombok.NonNull
private String name;
}
Cat.java
@Entity
@Table
@lombok.NoArgsConstructor
public class Cat extends Animal {
public Cat(Integer weight, String name) {
super(name);
this.weight = weight;
}
@lombok.Getter
private Integer weight;
}
Dog.java
@Entity
@Table
@lombok.NoArgsConstructor
public class Dog extends Animal {
public Dog(Integer age, String name) {
super(name);
this.age = age;
}
@lombok.Getter
private Integer age;
}
AnimalRepositoryImpl
和AnimalRepository
包含Cat和Dog存储库的一些共享代码。
AnimalRepository.java
@NoRepositoryBean
public interface AnimalRepository<T extends Animal> extends JpaRepository<T, Long> {
List<T> findAllByName(String name);
}
AnimalRepositoryImpl.java
public class AnimalRepositoryImpl<T extends Animal> {
@Autowired
AnimalRepository<T> animalRepository;
public List<T> findAllBySomeLogic() {
return animalRepository.findAll().stream().filter(animal -> !animal.getName().startsWith("Z")).collect(Collectors.toList());
}
}
现在我可以添加所有CatRepositories,它仍然有效(并且可以正常工作)。
CatRepository.java
@Transactional
public interface CatRepository extends AnimalRepository<Cat>, CatRepositoryCustom {
}
CatRepositoryCustom.java
public interface CatRepositoryCustom {
public List<Cat> findAllBySomeLogic();
}
CatRepositoryImpl.java
public class CatRepositoryImpl extends AnimalRepositoryImpl implements CatRepositoryCustom {
}
这是一个仍然只使用cat存储库的测试类。
AnimalRepositoryTest.java
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = TestConfiguration.class)
@ActiveProfiles(profiles = "test")
public class AnimalRepositoryTest {
@After
public void tearDown() {
catRepository.deleteAll();
}
@Autowired
private CatRepository catRepository;
@Test
public void shouldFindAllBySomeLogic() {
// given
catRepository.save(Lists.newArrayList(new Cat(2000, "Luna"), new Cat(2500, "Zoe"), new Cat(1800, "Toby")));
// when
List<Cat> cats = catRepository.findAllBySomeLogic();
// then
assertThat(cats.stream().map(c -> c.getName()).collect(Collectors.toList()), containsInAnyOrder("Luna", "Toby"));
}
@Test
public void shouldFindAllByName() {
// given
catRepository.save(Lists.newArrayList(new Cat(2000, "Luna"), new Cat(2500, "Zoe"), new Cat(1800, "Toby")));
// when
List<Cat> cats = catRepository.findAllByName("Luna");
// then
assertThat(cats.stream().map(c -> c.getName()).collect(Collectors.toList()), containsInAnyOrder("Luna"));
}
}
我编码的方式主要受this question启发(但我的情况更复杂)。
所以...主要问题。 - 如何为Dog
添加存储库(几乎与Cat
个存储库相同)而不是像NoUniqueBeanDefinitionException: No qualifying bean of type...
这样的存储库?我已经尝试了@Qualifier
的一些变体,但似乎在这种情况下不起作用。或者我可能完全错了。
答案 0 :(得分:1)
我发现至少有一个与类的泛型定义相关的失败。 CatRepositoryImpl类扩展了没有任何泛型类型的classe AnimalRepositoryImpl。 (请参阅帖子的以下两个代码段)
public class CatRepositoryImpl extends AnimalRepositoryImpl implements CatRepositoryCustom {
}
public class AnimalRepositoryImpl<T extends Animal> {
}
在我看来应该是这样的。
public class CatRepositoryImpl extends AnimalRepositoryImpl<Cat> implements CatRepositoryCustom {
}
除此之外,我会避免在Repository类中执行与逻辑相关的事情并将其移至服务级别。