我是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的教程指南中,它演示了如何扩展CrudRepository接口,但没有指定如何设置基于Spring的DAO,该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 DAOs中使用HQL的标准方式吗?我已经看到了@Transactional注解被放在DAO类的impl前面的例子(例如CustomerDAOImpl)?
请让我知道这是否是构建我的Spring Boot应用程序的编写方式,或者我应该只扩展/添加到CrudRepository?
如果有人能纠正我的例子,并给我指出一个URL,其中谈到使用连接的实体的HQL,我将非常感激。
Spring Boot指南并没有描述joins或DAOs -我只需要学习如何正确地创建查找器方法来模拟select语句,从而返回列表或数据结构。
感谢您抽出时间阅读这篇文章。
发布于 2015-04-01 16:03:12
如果我没理解错你的问题,你有两个问题:
关于第一个问题,我想指出的是,这是一个关于使用Hibernate作为JPA提供者的spring-data-jpa的问题,而不是spring-boot。
使用Spring Data时,我通常会完全跳过创建DAO,而直接使用自定义存储库来扩展标准的存储库,比如CrudRepository。因此,在您的示例中,您甚至不需要编写比以下代码更多的代码:
@Repository
public interface StudentRepository extends CrudRepository<Student, Long> {
List<Student> findByStudentName(String studentName);
}这就足够了,如果您使用
@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);
}发布于 2015-04-01 09:13:00
如果您使用@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>();
}
} https://stackoverflow.com/questions/29381058
复制相似问题