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

Hibernate JPA spring boot org。冬眠PersistentObjectException:传递给persist的分离实体

宗波涛
2023-03-14

我使用的是Spring Boot 4、Hibernate和JPA注释。我遇到了这个错误

组织。冬眠PersistentObjectException:传递给persist的分离实体。

我试着在互联网上搜索,但没有找到正确的答案。我尝试使用merge而不是persist,但没有成功。此外,我认为在更新资源时使用merge

这是我的代码:

`

package com.matome.users.login.stats.springbootStarter.model;

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.persistence.NamedQueries;

import com.matome.users.login.stats.springbootStarter.userconstants.UserRepositoryConstants;

@NamedQueries({
      @NamedQuery(name = UserRepositoryConstants.NAME_GET_ALL_USERS,
          query = UserRepositoryConstants.QUERY_GET_ALL_USERS),
      @NamedQuery(name = UserRepositoryConstants.NAME_GET_USER_BY_ID,
      query = UserRepositoryConstants.QUERY_GET_USER_BY_ID),
      @NamedQuery(name = UserRepositoryConstants.NAME_GET_USER_BY_USERNAME,
      query = UserRepositoryConstants.QUERY_GET_USER_BY_USERNAME),
      @NamedQuery(name = UserRepositoryConstants.NAME_DELETE_USER,
      query = UserRepositoryConstants.QUERY_DELETE_USER)
})

@Entity
public class User implements Serializable{

    private static final long serialVersionUID = 1L;

    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    Long id;
    String username;
    String password;
    String phone;

    public Long getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

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

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }
}

`积垢服务

`

package com.matome.users.login.stats.springbootStarter.CRUDService;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.matome.users.login.stats.springbootStarter.model.User;
import com.matome.users.login.stats.springbootStarter.repository.UserRepository;


@Service
@Transactional
public class UserCRUDService {
    @Autowired
    UserRepository userRepository;

    public User createUser(User user) {
        userRepository.save(user);
        return user;
    }

    public User updateUser(User user) {
        User existingUser = userRepository.getUserById(user.getId());

        if (existingUser == null) {
           throw new NoResultException();
        }

        existingUser.setId(user.getId());
        existingUser.setUsername(user.getUsername());
        existingUser.setPhone(user.getPhone());
        existingUser.setPassword(user.getPassword());
        userRepository.update(user);
        return user;
    }

    public User deleteUser(long id) {
        User user = userRepository.getUserById(id);

        if (user == null) {
          throw new NoResultException();
        }

        userRepository.delete(user);
        return user;
    }

}

`

存储库

`

    package com.matome.users.login.stats.springbootStarter.repository;

import java.util.List;

import javax.persistence.TypedQuery;

import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.matome.users.login.stats.springbootStarter.model.User;
import com.matome.users.login.stats.springbootStarter.userconstants.UserRepositoryConstants;

@Repository
@Transactional
public class UserRepository extends AbstractRepository<User> {
    TypedQuery<User> query;

    public List<User> getAllUsers() {
        query = entityManager.createNamedQuery(UserRepositoryConstants.NAME_GET_ALL_USERS, User.class);
        return query.getResultList();
    }

    public User getUserById(long id) {
        query = entityManager.createNamedQuery(UserRepositoryConstants.NAME_GET_USER_BY_ID, User.class);
        query.setParameter("id", id);
        return query.getSingleResult();
    }

    public User getUserByUsername(String username) {
        query = entityManager.createNamedQuery(UserRepositoryConstants.NAME_GET_USER_BY_USERNAME, User.class);
        query.setParameter("username", username);
        return query.getSingleResult();
    }
}

'抽象存储库

`

package com.matome.users.login.stats.springbootStarter.repository;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
public abstract class AbstractRepository<T> {

    @PersistenceContext
    protected EntityManager entityManager;

    @Transactional(propagation = Propagation.MANDATORY)
    public void save(T entity) {
        entityManager.persist(entity);
        entityManager.flush();
        entityManager.refresh(entity);
    }

    @Transactional
    public T update(T entity) {
        return entityManager.merge(entity);
    }

    @Transactional
    public void delete(T entity) {
        entityManager.remove(entity);
    }
}

`

工厂`

 package com.matome.users.login.stats.springbootStarter.factories;

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Service;

import com.matome.users.login.stats.springbootStarter.BackingForm.UserBackingForm;
import com.matome.users.login.stats.springbootStarter.model.User;
import com.matome.users.login.stats.springbootStarter.viewmodels.UserViewModel;

@Service
public class UserFactory {

    public UserViewModel createViewModel(User user) {
        UserViewModel viewModel = new UserViewModel();
        viewModel.setId(user.getId());
        viewModel.setUsername(user.getUsername());
        viewModel.setPhone(user.getPhone());
        return viewModel;
    }

    public List<UserViewModel> createVewModels(List<User> users) {
        List<UserViewModel> viewModels = new ArrayList<>();

        if (users != null) {
          for (User user : users) {
              viewModels.add(createViewModel(user));
          }
        }
        return viewModels;
    }

    public User createEntity(UserBackingForm userBackingForm) {
        User user = new User();
        user.setId(userBackingForm.getId());
        user.setUsername(userBackingForm.getUsername());
        user.setPassword(userBackingForm.getPassword());
        user.setPhone(userBackingForm.getPhone());
        return user;
    }

}

'支持形式

`

package com.matome.users.login.stats.springbootStarter.BackingForm;

public class UserBackingForm {
    private long id;
    private String username;
    private String password;
    private String phone;

    public long getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

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

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }
}

`

控制器

`

package com.matome.users.login.stats.springbootStarter.controller;

import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.matome.users.login.stats.springbootStarter.BackingForm.UserBackingForm;
import com.matome.users.login.stats.springbootStarter.CRUDService.UserCRUDService;
import com.matome.users.login.stats.springbootStarter.factories.UserFactory;
import com.matome.users.login.stats.springbootStarter.model.User;
import com.matome.users.login.stats.springbootStarter.repository.UserRepository;
import com.matome.users.login.stats.springbootStarter.viewmodels.UserViewModel;


@RestController
@RequestMapping("api")
public class UserController {
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private UserCRUDService userCRUDService;
    @Autowired
    private UserFactory userFactory;

    @RequestMapping(value = "/users", method = RequestMethod.GET)
    public Map<String, Object> getAllUsers() {
        Map<String, Object> map = new HashMap<>();
        map.put("users", userRepository.getAllUsers());
        return map;
    }

    @RequestMapping(value = "{id}", method = RequestMethod.GET)
    public Map<String, Object> getUserById(@PathVariable long id) {
        Map<String, Object> map = new HashMap<>();
        map.put("user", userRepository.getUserById(id));
        return map;
    }


@RequestMapping(value = "/user/add", method = RequestMethod.POST)
public UserViewModel addUser(@RequestBody UserBackingForm form) {
    User user = userFactory.createEntity(form);
    //user.setIsActive(true);
    user = userCRUDService.createUser(user);
    return userFactory.createViewModel(user);
 }

@RequestMapping(value = "/user/add/{id}", method =    RequestMethod.PUT)
public Map<String, Object> updateUser(@PathVariable("id") Long id, @RequestBody User user) {
    Map<String, Object> map = new HashMap<>();
    user.setId(id);
    map.put("updatedUser", userCRUDService.updateUser(user));
    return map;
}

@RequestMapping(value = "/test", method = RequestMethod.GET)
public String testFinal() {
    return "User test sucessfully";
}

@RequestMapping(value = "{id}", method = RequestMethod.DELETE)
public void deleteUser(@PathVariable("id") Long id) {
    User user = userRepository.getUserById(id);
    userRepository.delete(user);
}

}

`

视图模型

`

  package com.matome.users.login.stats.springbootStarter.viewmodels;

public class UserViewModel extends BaseViewModel<Long> {
    private String username;
    private String phone;

    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
}

`

基本视图模型

`
  package com.matome.users.login.stats.springbootStarter.viewmodels;

public abstract class BaseViewModel<T> {

  private T id;

  public T getId() {
    return id;
  }

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

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
    return result;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj)
      return true;
    if (obj == null)
      return false;
    if (getClass() != obj.getClass())
      return false;
    @SuppressWarnings("unchecked")
    BaseViewModel<T> other = (BaseViewModel<T>) obj;
    if (getId() == null) {
      if (other.getId() != null)
        return false;
    } else if (!getId().equals(other.getId()))
      return false;
    return true;
  }

}

`

主要

`    


  package com.matome.users.login.stats.springbootStarter;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Main { public static void main(String[] args) {
        SpringApplication.run(Main.class,args);

    }

}

'堆栈跟踪

`

org.hibernate.PersistentObjectException: detached entity passed to persist: com.matome.users.login.stats.springbootStarter.model.User
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:124) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:58) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:775) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:748) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:753) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1146) ~[hibernate-entitymanager-5.0.11.Final.jar:5.0.11.Final]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_131]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_131]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_131]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_131]
    at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:347) ~[spring-orm-4.3.4.RELEASE.jar:4.3.4.RELEASE]
    at com.sun.proxy.$Proxy78.persist(Unknown Source) ~[na:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_131]

`

共有2个答案

江鸿羲
2023-03-14

你能提供完整的堆栈跟踪吗?

给你一些提示:你应该只在服务级别设置@Transactional,而不是道/存储库。

EntityManager刷新方法意味着从数据库中获取数据以重新创建实体。如果您只是持久化实体,则无需刷新它。

@Transactional(propagation = Propagation.MANDATORY)
public void save(T entity) {
    entityManager.persist(entity);
    entityManager.flush();  //  This is not really usefull on a small transaction
    entityManager.refresh(entity); // No need for that : persist means entity already in sync
}

在更新方面,如果您有一个托管实体,则无需将其同步回数据库,JPA会自动处理。(合并数据库中的推送实体,强制更新所有列):

public User updateUser(User user) {
    User existingUser = userRepository.getUserById(user.getId());

    // ...
    existingUser.setPassword(user.getPassword());
    // ...
    userRepository.update(user);  // This is not needed !
    return user;
}

如果你想要最简单的东西,你应该看看龙目山。它将帮助您编写最简单的bean(@Data以生成getter/setter…)您使用的是Spring,所以也可以看看Spring数据JPA,它为您编写了一些繁琐的代码。

吴山
2023-03-14

在我看来,问题在于您已将用户实体的id声明为自动生成:

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

在创建用户对象时,手动设置id:

 public User createEntity(UserBackingForm userBackingForm) {
    User user = new User();
    user.setId(userBackingForm.getId());
    ...

因此,当您将其传递给persist/save时,持久化提供程序将不允许这样做,因为它希望客户端不会设置id

底线是,当你打算保留一个新条目时,你不应该设置关于当前配置的id,你应该没事。

 类似资料:
  • 我编写了第一个java应用程序来读取rss流,并使用,,。我的模特<代码>RssFeed: : 和: 我使用处理数据。如果不使用多对多功能保存RssFeed,则可以: 但当我加上一句话: 获取异常:。 我的RssFeedServiceImpl: } 和RssCategoryServiceImpl: 拯救多少对多少?

  • 初始数据。专业有很多科目。 专业JAVA 对于一个主题来说,专业不能为空。我希望它能以下一种方式工作:当我保存/更新/分离一个主题时,同样的操作必须应用于专业。当我删除一个主题时,专业不会发生任何变化。 主题JAVA 我写了一个集成测试。生成专业()和生成主题()这只是util方法。 你可以在这张图片上看到测试结果。 subjectService在此处引发了异常。保存(主题1); 原因:org。冬

  • 在我的spring应用程序中,我尝试在数据库中持久化以下实体: 我面临着这个错误: atribute密钥位于Atributo类: 保存操作的处理方式如下: 有人能指出一个正确的方向来维持这个实体吗? 注:项目的完整代码可以在这里找到: https://github.com/klebermo/webapp_horario_livre

  • JPA和Hibernate的新手,所以请耐心等待,因为我试图绘制一整张图片。所以我有两个具有双向关系的Java对象。员工类是拥有类,部门类是关系的反面。一个部门可以有许多员工,一个员工只能有一个部门。我分配了employee_id作为员工实体的主键,department_id作为部门实体的主键。我还想在员工类中使用department_id作为外键。 员工类 部门类 我用来生成两个对象并将它们保存

  • 我是Hibernate的新手,我需要帮助。 我有一个名为Kasa的表,它有3个属性-id、address和account\u id。在我的表中有12行。我想使用Hibernate对此进行映射,并使用Java添加新的映射,所以我这样做了: 我也有能手和二传手,但不需要复制。 现在我想在我的数据库中添加新行,如下所示: 我得到这样的错误:javax.persistence.PeristenceExce

  • 我有两个模型,一个用于存储用户详细信息,使用该Id,我试图将用户位置保存在另一个表中,该表使用用户的相同Id作为主键。 为什么我会出现这个错误?坚持是什么意思?我正在使用MySQL数据库(&I)