繁体   English   中英

如何修复传递给 spring boot 后端和角度前端的分离实体?

[英]How to fix detached entity passed to persist in spring boot back end and angular front end?

我正在实现一项功能以添加用户以及数据库中的一个或多个现有角色。 从角度前端成功添加了角色。 当我在角度前端创建一个新用户并向该用户添加多个角色时,我在 spring boot 后端获得了对象,但是它抛出了与 userServiceImpl 类中的 jpa save 方法相关的异常。

org.hibernate.PersistentObjectException:传递给持久化的分离实体:com.app.model.Role

[
    {
        "roleId": 1,
        "name": "USER",
        "description": "Role assigned to regular users who perform regular tasks within the application, such as add or update transactions and companies"
    },
    {
        "roleId": 2,
        "name": "ADMIN",
        "description": "Role assigned to users who can create other users, roles and perform regular users tasks within the Investment application"
    }
]

在 UI(角度前端)中,我需要创建新用户并为他们分配一个或多个现有角色。 我可以从控制台看到我添加的角色在那里,但是我没有在 spring boot 后端收到角色,只有常规用户信息,如姓名、姓氏、电子邮件、密码,但没有收到角色。

这是我创建用户的用户组件。

import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { Role } from 'src/app/model/Role';
import { User } from 'src/app/model/User';
import { RoleServiceService } from 'src/app/services/role-service.service';
import { UserServiceService } from 'src/app/services/user-service.service';

@Component({
  selector: 'app-user',
  templateUrl: './user.component.html',
  styleUrls: ['./user.component.css']
})
export class UserComponent implements OnInit {

  user!: User;
  createForm!:FormGroup;
  errorMessage!:string;
  role: Role[]= [];


  constructor(private userService: UserServiceService,
              private router: Router,
              private roleService: RoleServiceService) { }

  ngOnInit(): void {

    this.getAllRoles();

    this.createForm = new FormGroup({
      'userId': new FormControl(),
      'firstName': new FormControl(null, Validators.required),
      'lastName': new FormControl(null, Validators.required),
      'email': new FormControl(null, Validators.required),
      'password': new FormControl(null, Validators.required),
      'roles': new FormControl()
    });
  }


  onSubmit(){

    this.user = new User(

      this.createForm.get('userId')?.value,
      this.createForm.get('firstName')?.value,
      this.createForm.get('lastName')?.value,
      this.createForm.get('email')?.value,
      this.createForm.get('password')?.value,
      this.createForm.get('roles')?.value

    )

    console.log(this.user);

    this.userService.addUser(this.user).subscribe(
      data=>{
        this.router.navigate([""]);
      }, err=>{
        this.errorMessage = "Unable to add user!";
        console.log(err);
      }
    )

  }

  getAllRoles(){
    this.roleService.getAllRoles().subscribe(
      data=>{
        this.role = data;
        console.log(data);
      }
    )
  }

}

在后端,这是我添加用户的用户服务。 这是部分工作,因为我没有从角度获得角色。

@Override
public User addUser(User newUser) throws Exception {
    
    List<User> users = userRepo.findAll();
    
    for(User user: users) {
        if(user.getEmail().equalsIgnoreCase(newUser.getEmail())) {
            throw new Exception("User already exists");
        }
    }
    
    Set<Role> roles = newUser.getRoles();
    
    for (Role role : roles) {
        newUser.addRole(role);
    }
    
    return userRepo.save(newUser);
}

我在控制器中的映射方法是这样的:

@PostMapping("/register")
public ResponseEntity<?> addUser(@RequestBody User user) throws Exception{
        
    System.out.println(user);
    return new ResponseEntity<>(userService.addUser(user), HttpStatus.CREATED);
}

java中的用户实体:

import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.Transient;

@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false, updatable = false)
    private long userId;

    @Column(name = "first_name")
    private String firstName;

    @Column(name = "last_name")
    private String lastName;

    @Column(name = "email")
    private String email;

    @Column(name = "password")
    private String password;

    
    @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinTable(name="user_roles", joinColumns = @JoinColumn(name="user_id", referencedColumnName = "id"),
            inverseJoinColumns = @JoinColumn(name="role_id", referencedColumnName = "id") )
    
    private Set<Role> roles = new HashSet<>();

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

    public User() {

    }

    public User(String firstName, String lastName, String email, String password, Set<Role> roles) {
        super();
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
        this.password = password;
        this.roles = roles;
    }

    public long getUserId() {
        return userId;
    }

    public void setUserId(long userId) {
        this.userId = userId;
    }

    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 String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

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

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

    @Override
    public String toString() {
        return "User [userId=" + userId + ", firstName=" + firstName + ", lastName=" + lastName + ", email=" + email
                + ", password=" + password + ", roles=" + roles + "]";
    }

}

Angular Front end中的模型:

import { Role } from "./Role";


export class User{

    constructor(public userId: number,
                public firstName: string,
                public lastName: string,
                public email: string,
                public password:string,
                public roles: Role){

    }
    
}

Role 实体在 Java 中如下:

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

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false, updatable = false)
private Integer roleId;

@Column(name = "role_name")
private String name;

@Column(name = "description")
private String description;


public Role() {
}

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

public int getRoleId() {
    return roleId;
}

public void setRoleId(int roleId) {
    this.roleId = roleId;
}

public String getName() {
    return name;
}

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

public String getDescription() {
    return description;
}

public void setDescription(String description) {
    this.description = description;
}

}

Angular前端的角色模型是:

export class Role{

    constructor(public roleId: number,
                public name: string,
                public description:string){

    }

    
}

我确信它与我如何以反应形式添加角色有关,因为它是一组角色,但我不确定如何处理。

感谢您在我的代码中的一些关键问题上提供的帮助。 一旦我理解了以下内容,我就能够修复它:

问题:

  1. Java 和 Angular 的用户对象键名。 在我的 Java 用户实体中,实例变量名称之一是带有 s 的“角色”,而在角度角色实体中,同一字段被称为没有 s 的角色。

  2. 在 spring boot 后端(Java)。 在用户实体中,我添加了一个 addRole 方法,并在我的 userServiceImpl 服务中使用它,这导致传递的分离实体持续存在错误/异常。 为了解决这个问题,我所做的只是从我的服务中删除 addRole 方法,现在我可以创建用户并添加我想要的任何角色或多个角色,并且所有这些都正确保存在数据库中。

该服务现在如下所示:

 @Override
public User addUser(User newUser) throws Exception {
    
    List<User> users = userRepo.findAll();
    
    for(User user: users) {
        if(user.getEmail().equalsIgnoreCase(newUser.getEmail())) {
            throw new Exception("User already exists");
        }
    }
    
    return userRepo.save(newUser);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM