Spring Boot& amp; 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的教程指南中,它说明了如何扩展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 - 我只需要学习如何正确创建查找返回列表或数据结构的select语句的finder方法。
感谢您花时间阅读此内容......
答案 0 :(得分:11)
如果我理解你的问题是正确的,你有两个问题:
关于第一个问题,我想指出这是spring-data-jpa
使用Hibernate作为JPA提供程序的问题,而不是spring-boot
。
使用Spring数据我通常会完全跳过创建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);
}
答案 1 :(得分:1)
如果您使用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>();
}
}