使用Spring Boot Framework对基于Spring JPA的DAO进行分层的正确方法

Pac*_*ver 10 spring hibernate jpa hql spring-boot

我是Spring Boot和JPA的新手......

假设我有两个实体映射到两个表,这两个表在数据库中连接.

学生 - 1 ------ < - 课程

另外,假设已经创建并填充了数据库.

这表明一个学生有很多课程......

我的学生实体:

@Entity
public class Student {

    @OneToMany(mappedBy="student")
    private List<Courses> courses;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "Student_Id")
    private long studentId;

    @Column(name = "Student_Name")
    private String studentName;

    protected Student() { }

    // Getters & Setters
}
Run Code Online (Sandbox Code Playgroud)

我的课程实体:

@Entity
public class Course {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "Course_Id")
    private long courseId;

    @Id
    @Column(name = "Student_Id")
    private long studentId;

    @ManyToOne
    @PrimaryKeyJoinColumn(name="Student_Id", referencedColumnName="Student_Id")
    private Student student;

    @Column(name = "Course_Name")
    private String courseName;

    // Getters & Setters

}
Run Code Online (Sandbox Code Playgroud)

在Spring Boot的教程指南中,它说明了如何扩展CrudRepository接口,但它没有指定如何设置基于Spring的DAO,其中包含在其中使用HQL和EntityManager的自定义查找程序方法.

以下DAO和DaoImpl是否正确?

public interface CourseDao {
    List<Course> findCoursesByStudentName(String studentName);
}

@Repository
public class CourseDaoImpl implements CourseDao {

    @PersistenceContext
    EntityManager em;

    public List<Course> findCoursesByStudentName(String studentName) {
        String sql = "select c.courseName" +
                     "from Course c, Student s " +
                     "where c.course_id = s.student_id " +
                     "and s.studentName = :studentName ";

        Query query = em.createQuery(sql);
        query.setParameter("studentName", studentName);
        return query.getResultList();
    }
}   
Run Code Online (Sandbox Code Playgroud)

然后在客户端代码中,例如,在主类中:

 public class Application {

    @Autowired
    CustomerDao dao;

    public static void main (String args []) {
        List<Course> courses = dao.findCoursesByStudentName("John");
    }   
 }
Run Code Online (Sandbox Code Playgroud)

这是在Spring DAO中使用HQL的标准方法吗?我已经看到@Transactional注释的例子被添加到DAO类的impl(例如CustomerDAOImpl)之前?

如果这是构建我的Spring Boot应用程序的写入方式,或者我应该仅扩展/添加到CrudRepository,请告诉我?

如果有人可以更正我的示例并指向我使用已加入的实体来讨论HQL的URL,我将非常感激.

Spring Boot指南没有描述连接或DAO - 我只需要学习如何正确创建finder方法,该方法模拟返回列表或数据结构的select语句.

感谢您抽时间阅读...

dan*_*ten 12

如果我理解你的问题是正确的,你有两个问题:

  1. 如何创建DAO和DAOImpl?
  2. 在哪里放置您的交易注释?

关于第一个问题,我想指出这是一个关于将spring-data-jpaHibernate用作JPA提供程序的问题,而不是spring-boot.

使用Spring Data我通常会完全跳过创建DAO但直接使用自定义存储库扩展标准的类似CrudRepository.因此,在您的情况下,您甚至不必编写更多代码:

@Repository
public interface StudentRepository extends CrudRepository<Student, Long> {

    List<Student> findByStudentName(String studentName);

}
Run Code Online (Sandbox Code Playgroud)

这将是足够的,如果您使用,Spring Data将负责使用正确的实现填充它

@Autowired
StudentRepository studentRepo; 
Run Code Online (Sandbox Code Playgroud)

在您的服务类中.这也是我通常用我的方法注释的地方,@Transactional以确保一切都按预期工作.

关于你关于HQL的问题,请查看spring数据jpa文档,它指出对于大多数情况来说,在接口中坚持使用正确的命名方法或者进行命名查询(第3.3.3节)或使用@Query注释(第3.3.4节)手动定义查询,例如应该工作(没试过):

@Repository
public interface @CourseRepository extends CrudRepository<Course, Long> {

    @Query("select c.courseName from Course c, Student s where c.course_id = s.student_id and s.studentName = :studentName")
    public List<Course> findCoursesByStudentName(String studentName);

}
Run Code Online (Sandbox Code Playgroud)


sha*_*zin 2

如果您使用注释CourseDaoImpl@Transactional假设您已JpaTransactionManager正确定义),您只需检索具有匹配名称的学生并调用该getCourses()方法来延迟加载附加到该学生的课程。由于findCoursesByStudentName将在事务中运行,因此它将很好地加载课程。

@Repository
@Transactional(readOnly=true)
public class CourseDaoImpl implements CourseDao {

    @PersistenceContext
    EntityManager em;

    public List<Course> findCoursesByStudentName(String studentName) {
        String sql = "select s " +
                     "from Student s " +
                     "where s.studentName = :studentName ";

        Query query = em.createQuery(sql);
        query.setParameter("studentName", studentName);
        User user = query.getSingleResult();
        if(user != null) {
            return user.getCourses();
        }

        return new ArrayList<Course>();
    }
}   
Run Code Online (Sandbox Code Playgroud)