JPA组合键@OneToOne(PersistentObjectException)

时间:2014-10-07 00:12:34

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

这是您的情况

  1. 用户
  2. 发票
  3. InvoiceId 类(复合键
  4. 我无法将现有的User对象(从数据库中检索)合并到新的发票对象中为什么?有什么建议吗?

    @Entity
    @Table(name = "DA_USER")
    public class User implements Serializable {
    
        @Id
        @Column(name = "ID")
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
    
        @Column(name = "USERNAME",unique = true, nullable = false , length = 50)
        private String username;
    
        @Temporal(TemporalType.TIMESTAMP)
        @Column(name = "TIMESTAMP_OF_REGISTRATION", unique = false, nullable = true, updatable = false, columnDefinition = "TIMESTAMP")
        private Date timestampOfRegistration;   
    
        @Column(name = "PASSWORD",unique = false, nullable = false , length = 60)
        private String password;
    
        @Column(name = "NON_EXPIRED",unique = false, nullable = false)
        private boolean accountNonExpired;
    
        @Column(name = "CREDENTIAL_NON_EXPIRED",unique = false, nullable = false)
        private boolean credentialsNonExpired;    
    
        @Column(name = "NON_LOCKED",unique = false, nullable = false)
        private boolean accountNonLocked;
    
        @Column(name = "ENABLED",unique = false, nullable = false)
        private boolean enabled;
    
        @ManyToMany(fetch=FetchType.EAGER)
        @JoinTable(name = "DA_USER_ROLES", joinColumns = @JoinColumn(name = "USER_ID"), inverseJoinColumns = @JoinColumn(name = "ROLE_ID"))   
        private Set<Role> roles;
    
        // getters and setters
    }
    
    
    public class InvoiceId implements Serializable {
        private Long id;
        private Long user;
    
        // getters , setters , equals and hashCode
    }
    
    @Entity
    @Table(name = "DA_INVOICE")
    @IdClass(InvoiceId.class)
    public class Invoice implements Serializable {
    
        private static final long serialVersionUID = 4101444312504776489L;
    
        @Id
        @Column(name = "ID")    
        private Long id;    
    
        @Id
        @OneToOne(cascade = {CascadeType.MERGE})
        @JoinColumn(name = "USER_ID")
        private User user;  
    
        @Column(name = "TOTAL_AMOUNT", nullable = false)
        private Double totalAmount;
    
        // getters and setters
    }
    
    
    // invoice controller
    @Controller
    @RequestMapping("/invoice")
    public class InvoiceController {
        public String createInvoice(Locale locale, Model model,@AuthenticationPrincipal SecurityUser securityUser, Pageable pageable) {
        // getting an existing user from the database
        User user = userRepository.findOne(securityUser.getId());
    
        Invoice invoice1 = new Invoice();
        invoice1.setUser(user);
        invoice1.setId(12l);
        invoice1.setTotalAmount(250.0);
        invoiceRepository.save(invoice1); // org.hibernate.PersistentObjectException: detached entity passed to persist: User
    
        return "invoice";
    }
    

    此处您是例外

    SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/payment] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: com.emad.payment.domain.User; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.emad.payment.domain.User] with root cause
    org.hibernate.PersistentObjectException: detached entity passed to persist: com.emad.payment.domain.User
    

1 个答案:

答案 0 :(得分:0)

你的问题是有一个独立的实体:

  

传递给persist的分离实体:com.emad.payment.domain.User

您需要在交易期间保持交易打开。类似的东西:

entityManager.getTransaction().begin();
User user = getUserFromDB();
Invoice invoice = // get the invoice or use an invoice received as method param
user.setInvoice(invoice);
invoice.setUser(user);
entityManager.persist(invoice);
entityManager.getTransaction().commit();

对于服务层中的spring框架,您可以执行以下操作:

@Service
public class InvoiceService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private InvoiceRepository invoiceRepository;

    @Transactional
    public void createInvoice(Long invoiceId, Double totalAmount, Long userId) {
        User user = userRepository.findOne(userId);
        Invoice invoice = new Invoice();
        invoice.setUser(user);
        invoice.setId(invoiceId);
        invoice.setTotalAmount(totalAmount);
        invoiceRepository.save(invoice);
    }
}