【问题标题】:Spring Hibernate: @Transactional is not working in Spring Data JPA despite being configuredSpring Hibernate:尽管已配置 @Transactional 在 Spring Data JPA 中不起作用
【发布时间】:2018-11-06 07:18:16
【问题描述】:

在多对多关系中使用延迟评估时,我一直收到此错误:

LazyInitializationException: 延迟初始化角色集合失败,无法初始化代理 - 没有会话

我知道使用 Eager fetch 类型可以正常工作,但这会让人头疼并且会导致应用程序的性能滞后,因此,我必须继续考虑 Lazy fetch 类型。

我读到在使用 Spring Data JPA 时,@Transactional 会初始化惰性关系,但它似乎对我不起作用。

这是我的应用的外观:

实体

课程实体

@Entity
@Table(name = "course")
@Transactional
public class Course {


@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;

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

@Column(name = "course_description")
private String courseDescription;

@ManyToMany(cascade = {CascadeType.MERGE,CascadeType.DETACH,CascadeType.REFRESH,CascadeType.PERSIST})
@JoinTable(
        name = "course_student",
        joinColumns = @JoinColumn(name = "course_id"),
        inverseJoinColumns = @JoinColumn(name = "student_id") )
private List<Student> students;

学生实体

@Entity
@Table(name = "students")
public class Student {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;

private String name;

private String grade;

@ManyToMany(cascade = {CascadeType.MERGE,CascadeType.DETACH,CascadeType.REFRESH,CascadeType.PERSIST},fetch = FetchType.EAGER)
@JoinTable(
        name = "course_student",
        joinColumns = @JoinColumn(name = "student_id"),
        inverseJoinColumns = @JoinColumn(name = "course_id") )
List<Course> courses;

控制器

@Controller
@RequestMapping("/courses")
@Transactional
public class CourseController {

....

@GetMapping("get-joined-students")
ModelAndView getJoined() {

    Course course = courseRepo.findById(6).get();

    for (Student student :
            course.getStudents()) {

        System.out.println("Student: " + student);
    }


    ModelAndView modelAndView = new ModelAndView("redirect:list");

    return modelAndView;
}

}

存储库

课程资料库

@Repository
public interface CourseRepo extends JpaRepository<Course,Integer> {}

学生资料库

@Repository
public interface StudentRepo extends JpaRepository<Student,Integer> { }

Servlet 配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"  ....    >

<context:annotation-config/>

<context:component-scan base-package="com.company.springdemo"/>

<mvc:annotation-driven/>

....

<jpa:repositories transaction-manager-ref="transactionManagerJPA" base-package="com.company.springdemo" entity-manager-factory-ref="EMF" />

<bean id="transactionManagerJPA" class="org.springframework.orm.jpa.JpaTransactionManager" >
    <property name="dataSource" ref="myDataSource" />
</bean>

<tx:annotation-driven transaction-manager="transactionManagerJPA" />


<bean id="EMF"
      class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="packagesToScan" value="com.company.springdemo.entity" />
    <property name="dataSource" ref="myDataSource" />

    <property name="jpaProperties">
        <props>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQL57Dialect</prop>
            <prop key="hibernate.show_sql">false</prop>
            <prop key="hibernate.format_sql">true</prop>
        </props>
    </property>

    <property name="persistenceProvider">
        <bean class="org.hibernate.jpa.HibernatePersistenceProvider" />
    </property>
</bean>

我可能做错了什么?

【问题讨论】:

  • 您能否具体说明是哪一行代码导致了问题?
  • 错误发生在for循环内部,调用此行course.getStudents()
  • 好的。能否提供控制器的完整源代码?
  • 控制器内部代码...谢谢!
  • @PiotrPodraza,我马上更新

标签: java spring hibernate spring-mvc spring-data-jpa


【解决方案1】:

将@Transactional 用于非公共方法需要aspectj 依赖。在代码中,相关方法似乎是包私有的。我希望改为公开应该可以解决问题。我遇到了同样的问题,这篇文章对我有帮助 Does Spring @Transactional attribute work on a private method?

【讨论】:

    【解决方案2】:

    我认为你在这里搞混了。 LazyInitializationException 正在弹出,因为您在事务已经结束时尝试获取关系。

    您有多种选择:

    1. 访问事务中的关系
    2. 使用 EAGER 获取
    3. 通过FETCH JOIN 使用自定义查询
    4. 使用投影

    也请阅读我的文章了解更多详情:https://arnoldgalovics.com/lazyinitializationexception-demystified/ https://arnoldgalovics.com/using-projections-in-your-data-access-layer/

    【讨论】:

    • 感谢您的回答。是的,我知道这个异常会弹出,因为我们在事务结束时访问关系,所以,我的问题仍然存在:我想初始化惰性实体而不急切地获取它们,使用 fetch join,也不使用投影
    • 换句话说,我希望您能详细说明您在使用问题中分类的 Spring Data JPA 接口方面的第一个建议。再次感谢!
    • 另外,如果可以的话,@Transactional注解怎么解决这个问题,以防我配置错了
    • 无论如何,您的控制器都标有@Transactional,因此它应该可以正常工作。您使用的是哪个 Spring 版本?您是从 Spring 还是从 JavaEE 导入 @Transactional 注解?
    • 我使用的是 Spring 5.0.5 ... 是的,@Transactional 注释已经导入,如下所示:import javax.transaction.Transactional;
    猜你喜欢
    • 2013-12-10
    • 2016-10-04
    • 1970-01-01
    • 2021-12-19
    • 2017-06-09
    • 2012-05-10
    • 2018-06-27
    • 1970-01-01
    • 2017-07-17
    相关资源
    最近更新 更多