java - 更改数据库设计以改进 Spring Data JPA 软删除和查询身份验证

标签 java spring spring-boot spring-data-jpa

我希望这个问题不是基于意见,但我们开始吧。 我正在开发一个小型 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/

相关文章:

java - 无法在项目 acme-module 上执行目标 org.apache.maven.plugins :maven-compiler-plugin:2. 3.2:compile (default-compile): 编译失败:

jquery - 如何在jquery selectize插件中设置从数据库中选择值

java - getPrincipal() 方法返回用户名而不是 UserDetails

Linux 上的 Java 服务 - 如何确保持续正常运行时间。守护进程、Shell 脚本还是 Wrapper?

java - 当委托(delegate)方法具有相同的保护时,如何处理保护子句并引发异常?

java - 导入 Xerces 库时无法构建应用程序(退出值 1)

java - 尝试在 Spring Boot/Spring Security Web 应用程序中打开 .css 文件时,为什么会收到 "405 - Method Not Allowed"错误?

java - 为什么我的应用程序无法启动(使用 hibernate 搜索配置)?

java - 使用 selenium xpath 动态查找前一个兄弟元素

java - 获取 @RestControllerAdvice 中带注释的 @Async 方法抛出的异常