Java Spring中JPA存储库界面投影的最佳实践?
我想知道是否有人能对我目前正在玩的模式给出反馈?它涉及到让一个实体实现一个DTO接口,该接口也在JpaRepository接口中使用(作为投影)——对于同一实体——以返回具有特定列的查询结果。DTO接口还有默认方法,允许实体和DTO代理的任何实例具有类似的行为 我想回答的问题是,这种模式是否有任何缺点,例如性能,可能会妨碍人们在生产中使用它。我还想听听其他人是如何使用JpaRepositories查询特定数据字段的。下面我有一个代码示例,演示了我正在使用的模式Java Spring中JPA存储库界面投影的最佳实践?,java,spring-data-jpa,nhibernate-projections,Java,Spring Data Jpa,Nhibernate Projections,我想知道是否有人能对我目前正在玩的模式给出反馈?它涉及到让一个实体实现一个DTO接口,该接口也在JpaRepository接口中使用(作为投影)——对于同一实体——以返回具有特定列的查询结果。DTO接口还有默认方法,允许实体和DTO代理的任何实例具有类似的行为 我想回答的问题是,这种模式是否有任何缺点,例如性能,可能会妨碍人们在生产中使用它。我还想听听其他人是如何使用JpaRepositories查询特定数据字段的。下面我有一个代码示例,演示了我正在使用的模式 public interface
public interface InstructorDTO {
String getFirstName();
String getLastName();
default String getFullName() {
return getFirstName() + ' ' + getLastName();
}
}
@Entity
public class Instructor implements InstructorDTO {
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
private int id;
@Column(name="first_name")
private String firstName;
@Column(name="last_name")
private String lastName;
@Column(unique = true)
private String email;
@Override
public String getFirstName() {
return this.firstName;
}
@Override
public String getLastName() {
return this.lastName;
}
...remaining getters and setters
}
@Repository
public interface InstructorRepository extends JpaRepository<Instructor, Integer> {
<S> S findById(int id, Class<S> type);
<T> Collection<T> findByEmail(String email, Class<T> type);
}
public class SomeClass {
@Autowired
InstructorRepository instructorRepository;
public void someMethod {
int id = 1;
// Returns proxy
InstructorDTO instructor1 = instructorRepository.findById(id, InstructorDTO.class);
// Returns Instructor Object
Instructor instructor2 = instructorRepository.findOne(id);
System.out.println(instructor1.getFullName()); // returns John Doe
System.out.println(instructor2.getFullName()); // returns John Doe
}
}
公共接口{
字符串getFirstName();
字符串getLastName();
默认字符串getFullName(){
返回getFirstName()+“”+getLastName();
}
}
@实体
公共课堂讲师实施讲师培训{
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
私有int-id;
@列(name=“first_name”)
私有字符串名;
@列(name=“last_name”)
私有字符串lastName;
@列(唯一=真)
私人字符串电子邮件;
@凌驾
公共字符串getFirstName(){
返回这个.firstName;
}
@凌驾
公共字符串getLastName(){
返回this.lastName;
}
…剩下的接受者和接受者
}
@存储库
公共接口讲师报告扩展了JpaRepository{
S findById(int-id,类类型);
收集findByEmail(字符串电子邮件,类类型);
}
公共类{
@自动连线
讲师或报告员讲师或报告员;
公开无效法{
int-id=1;
//返回代理
InstructorTo instructor1=instructorRepository.findById(id,InstructorTo.class);
//返回讲师对象
讲师讲师2=讲师报告.findOne(id);
System.out.println(instructor1.getFullName());//返回John Doe
System.out.println(instructor2.getFullName());//返回John Doe
}
}
相比之下,此解决方案没有缺点。如果只需要几列,使用DTO而不是实体要好得多
因为如果只在SQL上使用DTO,将生成用于选择数据的语句。其中,如果您使用实体,则可能会加载急切或延迟获取的关系,这可能会导致n+1选择问题
只有当您真的希望您的实体扩展DTO时,才有问题。我认为那没有道理
两项建议
- 不要使用@GeneratedValue(策略=GenerationType.AUTO)。为什么你能在这里找到
- 您可以删除@Repository,因为您的扩展来自JpaRepository