我希望这个问题不是基于意见,但我们开始吧。 我正在开发一个小型 API,使用 spring boot、spring data jpa 和 JWT Token 作为身份验证系统。 API 非常简单,是一个考试生成器,您可以在其中注册教授、类(class)、问题、选择等。
例如: [2017 年 11 月 13 日 - 编辑以包含 AbstractEntity]
@MappedSuperclass
public class AbstractEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
protected Long id;
protected boolean enabled = true;
//equals, hashcode...
}
public class Professor extends AbstractEntity{
private String email;
}
public class Course extends AbstractEntity {
@ManyToOne(optional = false)
private Professor professor;
}
public class Question extends AbstractEntity {
@ManyToOne(optional = false)
private Course course;
}
因为身份验证系统是所有查询的 JWT token ,所以我必须包含教授的信息。
例如
public interface CourseRepository extends PagingAndSortingRepository<Course, Long> {
@Query("select c from Course c where c.id = ?1 and c.professor = ?#{principal.professor} and c.enabled = true")
Course findOne(Long id);
}
问题是,对于每个 CRUD 查询,我都必须编写自己的自定义查询,因为教授的信息以及启用的字段。
我知道有一种方法可以扩展 PagingAndSortingRepository 并编写您自己的自定义查询,如下所示:
public interface CustomPagingAndSortRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID> {
@Override
@Query("select e from #{#entityName} e where e.id = ?1 and e.professor = ?#{principal.professor} and e.enabled = true")
T findOne(ID id);
//More fields overrided here
}
如果我只需要担心的话,这个 CustomPagingAndSortRepository 就可以完美地适用于所有类。该类非常适合 Course,因为 e.professor = ?#{principal.professor}
会在那里找到教授。但它不适用于问题,例如,因为我需要加入类(class)才能找到教授,例如 e.course.professor = ?#{principal.professor}
关键是,如果我在所有类(class)中与教授建立关联,我可以使通用代码正常工作,节省大量代码,但会牺牲数据库设计的规范化。 问题是:还有别的办法吗?或者这样做是否有效?
PS:问题、类(class)等不会改变所有者,这意味着只有创建的教授才能使用它。
最佳答案
为什么不创建一个带有 @Service
注释的类来 Autowiring 您的 CourseRepository
,然后将 id,principal.professor,enabled
传递给它,然后您的存储库将具有方法Course findByIdAndProfessorAndEnabled(Long id, String Professor, Booleanenabled)
。
代码片段:
public interface CourseRepository extends PagingAndSortingRepository<Course, Long> {
Course findByIdAndProfessorAndEnabled(Long id, Professor professor, Boolean enabled);
}
@Service
public class CourseService{
@Autowired
CourseRepository courseRepository;
//pass in principal.professor from your controller or from wherever this is called
public Course findByIdAndProfessorAndEnabled(Long id, Professor professor, Boolean enabled){
return courseRepository.findByIdAndProfessor(id, professor, enabled);
}
}
编辑:对于 Hibernate 模型
如果您始终希望在查询中将 enabled
设置为 true,则可以在模型上使用 @Where
注释
@MappedSuperclass
@Where(clause="is_enabled=true")
public class AbstractEntity implements Serializable {
.
.
.
@Column(name="is_enabled")
protected boolean enabled = true;
...
我不知道这种方法是否也适用于您的委托(delegate)人,但您可以尝试一下
关于java - 更改数据库设计以改进 Spring Data JPA 软删除和查询身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47225471/