【发布时间】:2015-07-10 15:46:51
【问题描述】:
这是一个简化的工作代码。有一个映射的超类和两个它的子类(在现实生活中超类当然包含更多字段)
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 的一些变化,但似乎在这种情况下不起作用。或者我做错了。
【问题讨论】:
-
你真的需要这个例子的 impl 类吗(即是为了演示问题)?
-
@chuchikaeschtli 是的,我愿意。当然,
findAllBySomeLogic()方法的逻辑可以很容易地通过一个简单的查询来实现——这只是一个例子。但在现实生活中,需要为一些复杂的存储库方法提供自定义实现。
标签: java spring spring-boot spring-data spring-data-jpa