使用 Spring Boot 框架对基于 Spring JPA 的 DAO 进行分层的正确方法
Posted
技术标签:
【中文标题】使用 Spring Boot 框架对基于 Spring JPA 的 DAO 进行分层的正确方法【英文标题】:Proper Way to layer Spring JPA based DAO using Spring Boot Framework 【发布时间】:2015-06-05 12:36:44 【问题描述】:刚接触 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
我的课程实体:
@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
在 Spring Boot 的 Tutorial Guides 中,它说明了如何扩展 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();
然后在客户端代码中,例如在主类中:
public class Application
@Autowired
CustomerDao dao;
public static void main (String args [])
List<Course> courses = dao.findCoursesByStudentName("John");
这是在 Spring DAO 中使用 HQL 的标准方式吗?我已经看到了将 @Transactional 注释添加到 DAO 类的 impl 的示例(例如 CustomerDAOImpl)?
如果这是构建我的 Spring Boot 应用程序的写入方式,或者我应该只扩展/添加到 CrudRepository,请告诉我?
如果有人可以纠正我的示例并将我指向一个使用连接的实体讨论 HQL 的 URL,我将非常感激。
Spring Boot 指南没有描述连接或 DAO - 我只需要学习如何正确创建 finder 方法来模拟返回列表或数据结构的 select 语句。
感谢您花时间阅读本文...
【问题讨论】:
【参考方案1】:如果我理解你的问题是正确的,你确实有两个问题:
-
如何创建DAO和DAOImpl?
将您的交易注释放在哪里?
关于第一个问题,我想指出,这是一个关于 spring-data-jpa
使用 Hibernate 作为 JPA 提供程序的问题,而不是 spring-boot
。
使用 Spring Data 我通常完全跳过创建 DAO,但直接使用自定义存储库扩展标准存储库,如 CrudRepository
。因此,在您的情况下,您甚至不必编写比以下更多的代码:
@Repository
public interface StudentRepository extends CrudRepository<Student, Long>
List<Student> findByStudentName(String studentName);
这已经足够了,如果你使用,Spring Data 会用正确的实现来填充它
@Autowired
StudentRepository studentRepo;
在您的服务类别中。这也是我通常用@Transactional
注释我的方法的地方,以确保一切都按预期工作。
关于您关于 HQL 的问题,请查看 spring data jpa documentation,它指出对于大多数情况,在接口中坚持使用正确的命名方法或进行命名查询就足够了(第 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);
【讨论】:
哪个更好? JPA 还是 Cruid 存储库?我们可以只使用存储库吗?上次我使用hibernate的时候有spring 2.5和hibernate 3,我不仅忘记了它是怎么回事,我也没有使用这些功能,在youtube上新看到它们之前......JPARepository
实际上是从CRUDRepository
继承的,所以它是处理JPA Pojos 的特定类型。见docs.spring.io/spring-data/jpa/docs/current/api/org/…
非常感谢,'如果您使用@Transactional
注释您的CourseDaoImpl
(假设您已正确定义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>();
【讨论】:
shazin,感谢您的回复...这是执行 HQL 的标准方法吗?您正在选择学生而不是加入?我很困惑......另外,为什么readOnly = true?正确定义 JpaTransactionManager 是什么意思?你会如何在 Spring Boot 中做到这一点?为什么不使用 CrudRespository?我正在寻求的是做事的标准方式......感谢您的帮助。 这个用户类/对象引用在哪里定义?你是说学生吗?以上是关于使用 Spring Boot 框架对基于 Spring JPA 的 DAO 进行分层的正确方法的主要内容,如果未能解决你的问题,请参考以下文章