当前位置: 首页 > 知识库问答 >
问题:

JPA对象引用了一个未保存的瞬态实例-在刷新之前保存该瞬态实例

楚博雅
2023-03-14

我真的很难解释为什么JPA不把我的@manytomy关系串联起来。我找到的所有答案都与缺少的cascade语句有关。但我确实有,而且仍然有:

原因:org.hibernate.瞬态对象异常:对象引用未保存的瞬态实例-在刷新之前保存瞬态实例:com.example.iaa.model.员工

代码基于本教程:https://hellokoding.com/jpa-many-to-many-relationship-mapping-example-with-spring-boot-maven-and-mysql/

package com.example.iaa.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.example.iaa.model.Employee;

public interface EmployeeRepository extends JpaRepository<Employee, Integer> {
}




package com.example.iaa.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.example.iaa.model.Role;

public interface RoleRepository extends JpaRepository<Role, Integer> {
}




package com.example.iaa.model;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

@Entity
@Table//(name = "role")
public class Role {

    @Id
    @GeneratedValue
    private int id;

    private String name;

    @ElementCollection
    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable//(name = "employee_role", joinColumns = @JoinColumn(name = "id_role", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "id_employee", referencedColumnName = "id"))
    private Set<Employee> employees;

    public Role(String name, HashSet<Employee> employees) {
        this.name = name;
        this.employees = employees;
    }

    public Role(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Set<Employee> getEmployees() {
        return employees;
    }

    public void setEmployees(Set<Employee> employees) {
        this.employees = employees;
    }

}




package com.example.iaa.model;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

@Entity
@Table//(name = "employee")
public class Employee {

    @Id
    @GeneratedValue
    private int id;

    private String firstName;
    private String lastName;

    @ElementCollection
    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable//(name = "employee_role", joinColumns = @JoinColumn(name = "id_employee", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "id_role", referencedColumnName = "id"))
    private Set<Role> roles;

    public Employee(String firstName) {
        this.firstName = firstName;
    }

    public Employee() {
        roles = new HashSet<Role>();
    }

    public Employee(String name, HashSet<Role> roles) {
        this.firstName = name;
        this.roles = roles;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getDisplayName() {
        return firstName + " " + lastName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public void addRole(Role role) {
        roles.add(role);
    }

    public Set<Role> getRoles() {
        return Collections.unmodifiableSet(roles);
    }

    public void setRoles(Set<Role> roles) {
        this.roles = roles;
    }

    public boolean hasRole(Role role) {
        return roles.contains(role);
    }

    @Override
    public String toString() {
        String ret = "";
        ret += "id: " + id + "\n";
        ret += "firstName: " + firstName + "\n";
        ret += "lastName: " + lastName + "\n";
        ret += "displayName: " + getDisplayName() + "\n";
        ret += "roles: ";

        String delim = "";
        for (Role role : roles) {
            ret += delim + role;
            delim = ",";
        }
        return ret;
    }
}




package com.example.iaa.controller;

import java.util.HashSet;

import javax.transaction.Transactional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.example.iaa.model.Employee;
import com.example.iaa.model.Role;
import com.example.iaa.repository.EmployeeRepository;
import com.example.iaa.repository.RoleRepository;

public class HelloJpaApplication {
    private static final Logger logger = LoggerFactory.getLogger(HelloJpaApplication.class);

    @Autowired
    private RoleRepository roleRepository;

    @Autowired
    private EmployeeRepository employeeRepository;

    @RequestMapping(value = "/jpa")
    @Transactional
    public String testJPA(final Model model) throws Exception {
        // save a couple of roles
        final Employee employeeA = new Employee("Employee A");
        final Employee employeeB = new Employee("Employee B");
        final Employee employeeC = new Employee("Employee C");

        roleRepository.save(new HashSet<Role>(){{
            add(new Role("Role A", new HashSet<Employee>(){{
                add(employeeA);
                add(employeeB);
            }}));

            add(new Role("Role B", new HashSet<Employee>(){{
                add(employeeA);
                add(employeeC);
            }}));
        }});

        // fetch all roles
        for(Role role : roleRepository.findAll()) {
            logger.info(role.toString());
        }

        // save a couple of employees
        final Role roleA = new Role("Role A");
        final Role roleB = new Role("Role B");

        employeeRepository.save(new HashSet<Employee>() {{
            add(new Employee("Employee A", new HashSet<Role>() {{
                add(roleA);
                add(roleB);
            }}));

            add(new Employee("Employee B", new HashSet<Role>() {{
                add(roleA);
                add(roleB);
            }}));
        }});

        // fetch all employees
        for(Employee employee : employeeRepository.findAll()) {
            logger.info(employee.toString());
        }
        return "soy:iaa.index";
    }
}

共有1个答案

燕智
2023-03-14

如链接所示,我在下面进行了更改

@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinTable(name = "employee_role", joinColumns = @JoinColumn(name = "id_employee", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "id_role", referencedColumnName = "id"))
private Set<Employee> employees;

@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "employees")
private Set<Role> roles;

还添加了默认构造函数和即时获取,然后它就工作了。

 类似资料: