我正在创建一个演示春季项目,其中讲师和课程之间存在一对多的双向映射。我创建了一个API来列出讲师和课程。
Instructor.java
@Entity
@Table(name="instructor")
public class Instructor {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id")
private int id;
@Column(name="first_name")
private String firstName;
@Column(name="last_name")
private String lastName;
@Column(name="email")
private String email;
/*
* instructor class has @OneToMany relationship with course
*/
//One instructor can have may course
@OneToMany(mappedBy="instructor",
cascade = { CascadeType.DETACH,
CascadeType.MERGE,
CascadeType.PERSIST,
CascadeType.REFRESH
}
)//it refers to instructor object/property defined in Course.java
private List<Course> courses;
//getter and setters
Course.java
@Entity
@Table(name="course")
public class Course {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id")
private int id;
@Column(name="title")
private String title;
/*
* course table has @ManyToOne mapping with Instructor
*/
@ManyToOne(cascade = { CascadeType.DETACH,
CascadeType.MERGE,
CascadeType.PERSIST,
CascadeType.REFRESH
})
@JoinColumn(name="instructor_id") //Course column name in instructor_id
/*
* instructor_id has a key that point to actual instructor id
* it's FK and it's relationship is defined in the db
*/
private Instructor instructor;
//getters and setters
CommonRestController.java
@RestController
@RequestMapping("/api")
public class CommonRestController {
//Inject Service
@Autowired
private CommonService theCommonService;
/*
* For COURSES
*/
//1. API to get Courses
@GetMapping("/Course/courses")
public List<Course> getCourses(){
return theCommonService.getCourses();
}
//---------------------------------------------
/*
* For INSTRUCTORS
*/
//1. API to get Instructors
@GetMapping("/Inst/instructors")
public List<Instructor> getInstructors(){
return theCommonService.getInstructors();
}
}
服务等级
CommonServiceImpl.java
//Inject Course DAO
@Autowired
private CourseDAO courseDAO;
//Inject Instructor DAO
@Autowired
private InstructorDAO instructorDAO;
//1. For Courses
@Override
@Transactional
public List<Course> getCourses() {
return courseDAO.getCourses();
}
//********************************************************************
//2. For Instructor
@Override
@Transactional
public List<Instructor> getInstructors(){
return instructorDAO.getInstructors();
}
}
DAO类
InstructorDAO类
//Inject Session Factory
@Autowired
private SessionFactory theSessionFactory;
@Override
public List<Instructor> getInstructors() {
//1. Start the Hibernate Session
Session theSession = theSessionFactory.getCurrentSession();
//2. Create the Instructor.... sort by last_name
Query<Instructor> theQuery = theSession.createQuery("from Instructor order by lastName",Instructor.class);
//3. Execute the query, get the resulted list
List<Instructor> tempInstructor = theQuery.getResultList();
/*
* For checking purpose
*/
for(int i=0 ; i<tempInstructor.size();i++) {
System.out.println(tempInstructor.get(i));
}
//4. Return the result
return tempInstructor;
}
}
CourseDAO类
//Inject SessionFactory
@Autowired
private SessionFactory theSessionFactory;
@Override
public List<Course> getCourses() {
// 1. Get Current Hibernate Session
Session theSession = theSessionFactory.getCurrentSession();
// 2. Create Query... order courses by title
Query<Course> theQuery = theSession.createQuery
("from Course order by title",Course.class);
// 3. Execute the query and get the result
List<Course> tempCourse = theQuery.getResultList();
/*
* Show Courses
*/
for(int i=0; i<tempCourse.size();i++) {
System.out.println(tempCourse.get(i));
}
// 4. Return the result
return tempCourse;
}
下面是配置Java类
DemoAppConfig.java
@Configuration
@EnableWebMvc
@EnableTransactionManagement
@ComponentScan("com.luv2code.springdemo")
@PropertySource({ "classpath:persistence-mysql.properties" })
public class DemoAppConfig implements WebMvcConfigurer {
@Autowired
private Environment env;
private Logger logger = Logger.getLogger(getClass().getName());
// define a bean for ViewResolver
@Bean
public DataSource myDataSource() {
// create connection pool
ComboPooledDataSource myDataSource = new ComboPooledDataSource();
// set the jdbc driver
try {
myDataSource.setDriverClass("com.mysql.jdbc.Driver");
}
catch (PropertyVetoException exc) {
throw new RuntimeException(exc);
}
// for sanity's sake, let's log url and user ... just to make sure we are reading the data
logger.info("jdbc.url=" + env.getProperty("jdbc.url"));
logger.info("jdbc.user=" + env.getProperty("jdbc.user"));
// set database connection props
myDataSource.setJdbcUrl(env.getProperty("jdbc.url"));
myDataSource.setUser(env.getProperty("jdbc.user"));
myDataSource.setPassword(env.getProperty("jdbc.password"));
// set connection pool props
myDataSource.setInitialPoolSize(getIntProperty("connection.pool.initialPoolSize"));
myDataSource.setMinPoolSize(getIntProperty("connection.pool.minPoolSize"));
myDataSource.setMaxPoolSize(getIntProperty("connection.pool.maxPoolSize"));
myDataSource.setMaxIdleTime(getIntProperty("connection.pool.maxIdleTime"));
return myDataSource;
}
private Properties getHibernateProperties() {
// set hibernate properties
Properties props = new Properties();
props.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
props.setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
return props;
}
// need a helper method
// read environment property and convert to int
private int getIntProperty(String propName) {
String propVal = env.getProperty(propName);
// now convert to int
int intPropVal = Integer.parseInt(propVal);
return intPropVal;
}
@Bean
public LocalSessionFactoryBean sessionFactory(){
// create session factorys
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
// set the properties
sessionFactory.setDataSource(myDataSource());
sessionFactory.setPackagesToScan(env.getProperty("hibernate.packagesToScan"));
sessionFactory.setHibernateProperties(getHibernateProperties());
return sessionFactory;
}
@Bean
@Autowired
public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
// setup transaction manager based on session factory
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory);
return txManager;
}
}
MySpringMvcDispatcherServletInitializer.java
public class MySpringMvcDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
// TODO Auto-generated method stub
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { DemoAppConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
期望的结果是获得讲师和课程的详细信息,而不是得到
“处理程序调度失败;嵌套异常为java.lang.StackOverflowError”
该如何解决?