簡體   English   中英

Spring Data/JPA 和 errorType :對象引用未保存的瞬態實例 - 在刷新之前保存瞬態實例

[英]Spring Data/JPA and errorType : object references an unsaved transient instance - save the transient instance before flushing

在此處輸入圖像描述

當我使用存儲庫 appUserRepository.save() 更新 Person 時,JPA 出現此錯誤:“ 2022-07-16 10:27:30.080 ERROR 4792 --- [nio-7777-exec-3] oaccC[.[. [/].[dispatcherServlet]:Servlet.service() for servlet [dispatcherServlet] 在路徑 [] 的上下文中拋出異常 [請求處理失敗;WeightRecord;嵌套異常是 java.lang.IllegalStateException:org.hibernate.TransientObjectException:對象引用未保存的瞬態實例 - 在刷新之前保存瞬態實例:com.quentingenet.openweighttracker.entity.WeightRecord] 根本原因“我查看了有關此錯誤的 stackoverflow 帖子,但找不到任何解決方案。 我還嘗試了 cascadeType.ALL。 就在下面,您可以在“WeightRecordController”類中看到發布方法“saveWeight”。 'personRepository.save(personToUpdate);' 調用時產生錯誤。

      @Entity
        @Table(name = "person")
        public class Person implements Serializable{
            
            private static final long serialVersionUID = 1L;
        
            @Id
            @GeneratedValue(strategy = GenerationType.IDENTITY)
            @Column(name="id_person")
            private Long idPerson;
        
            @ElementCollection
            private List<WeightRecord> userPersonnalWeightsRecord = new ArrayList<WeightRecord>();
            
            @OneToOne( cascade =  CascadeType.ALL, fetch = FetchType.EAGER)
            @JoinColumn(name = "id_initial_data")
            private InitialData userInitData;
            
            @OneToOne( cascade =  CascadeType.ALL, fetch = FetchType.EAGER)
            @JoinColumn(name = "id_user")
            private AppUser appUserPerson;
        
            @OneToOne(cascade =  CascadeType.ALL, fetch = FetchType.EAGER)
            @JoinColumn(name = "id_weight_record")
            private WeightRecord weightRecord;
    
    
    
        @Entity
        @Table(name = "weight_record")
        public class WeightRecord implements Serializable{
        
            private static final long serialVersionUID = 1L;
        
            @Id
            @GeneratedValue(strategy = GenerationType.IDENTITY)
            @Column(name = "id_weight_record")
            private Long idWeightRecord;
        
            @Column(name = "weight_record_date", nullable = true)
            private LocalDate weightRecordDate;
        
            @Min(1)
            @Max(635)
            @Column(name = "weight_kg_record", nullable = true, precision = 1)
            private Double weightKgRecord;
        
            @Min(1)
            @Max(99)
            @Column(name = "percent_fat_mass", nullable = true, precision = 1)
            private Double percentFatMass;
        
            @Min(1)
            @Max(99)
            @Column(name = "percent_muscular_mass", nullable = true, precision = 1)
            private Double percentMuscularMass;
        
            @Min(1)
            @Max(99)
            @Column(name = "percent_body_water", nullable = true, precision = 1)
            private Double percentBodyWater;
        
            @Min(1)
            @Max(99)
            @Column(name = "percent_bone_mass", nullable = true, precision = 1)
            private Double percentBoneMass;
    
    
    @Table(name = "initial_data")
    @Entity
    public class InitialData implements Serializable{
    
        private static final long serialVersionUID = 1L;
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "id_initial_data")
        private Long idInitialData;
    
        @Min(5)
        @Max(636)
        @Column(name = "goal_weight", nullable = true, precision = 1)
        private Double goalWeight;
    
        @Min(25)
        @Max(300)
        @Column(name = "body_size", nullable = true)
        private Integer bodySize;
    
        // @Size(min = 3, max = 5, message = "Please choose between MAN or WOMAN")
        @Column(name = "sex", nullable = true)
        private String sex;
    
        @Min(1917)
        @Max(2022)
        @Column(name = "year_birth", nullable = true)
        private Integer yearBirth;

@Entity
@Table(name = "app_users")
public class AppUser implements Serializable{

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id_user")
    private Long idUser;

    @NotEmpty
    @Size(min = 3, max = 36)
    @Column(name = "appUsername", nullable = false, unique = true)
    private String appUsername;

    @NotEmpty
    @Size(min = 4, max = 255)
    @Column(name = "password", nullable = false)
    private String password;



@RestController
@RequestMapping("/weights")
public class WeightRecordController {

    @Autowired
    WeightRecordServiceImpl weightRecordServiceImpl;

    @Autowired
    WeightRecordRepository weightRecordRepository;

    @Autowired
    AppUserRepository appUserRepository;

    @Autowired
    PersonRepository personRepository;

    private final Logger logger = LoggerFactory.getLogger(WeightRecordController.class);

    public Long getAppUserConnectedId(Principal principal) {
        // TODO user/principal is null... so exception is raise with message "User not
        // found"
        if (!(principal instanceof UsernamePasswordAuthenticationToken)) {
            throw new RuntimeException(("User not found"));
        }
        logger.info("USER IS PRESENT IN DATABASE FROM FUNCTION 'getAppUserConnectedId()'");
        UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) principal;
        AppUser appUserFinded = appUserRepository.findByAppUsername(token.getName());
        return appUserFinded.getIdUser();
    }



    // TODO
    @PostMapping
    public ResponseEntity<WeightRecord> saveWeight(@RequestBody WeightRecord weightRecord, Principal principal) {
        logger.info("POST /weights");
        Long appUserConnectedId = this.getAppUserConnectedId(principal);
        Optional<Person> personUserToSave = personRepository.findById(appUserConnectedId);
        logger.info("PERSON FINDED IN DATABASE");
        if (personUserToSave.isPresent()) {
            logger.info("USER IS PRESENT IN DATABASE FROM saveWeightController");
            weightRecordServiceImpl.saveWeightRecord(weightRecord);
            logger.info("WEIGHT RECORD IS SAVED NOW");
        } else {
            return new ResponseEntity<WeightRecord>(HttpStatus.BAD_REQUEST);
        }

        Person personToUpdate = personRepository.findById(appUserConnectedId).orElseThrow();
        List<WeightRecord> personWeightsList = personToUpdate.getUserPersonnalWeightsRecord();
        personWeightsList.add(weightRecord);
        personToUpdate.setUserPersonnalWeightsRecord(personWeightsList);
        logger.info("WEIGHT UPDATED IN PERSONNAL USER LIST WITH ID n°{}",appUserConnectedId);
        //TODO : FIX PROBLEM just bellow
        personRepository.save(personToUpdate);
        logger.info("PERSON WITH ID N°{} IS UPDATED NOW.", personToUpdate.getIdPerson());

        return new ResponseEntity<WeightRecord>(weightRecord, HttpStatus.CREATED);
    }

@Repository
public interface PersonRepository extends JpaRepository<Person, Long> {

}

一世

事實上,問題涉及實體映射。 我現在使用@OneToMany 而不是@ElementCollection 作為用戶的權重列表,沒關系。 在此更改后,我已導入我的實體的屏幕截圖。 感謝幫助 ! 只是在我的新實體 Person 中吼叫:

    @Entity
    @Table(name = "person")
    public class Person implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "id_person")
        private Long idPerson;
    
        @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
        @JoinColumn(name = "id_initial_data")
        private InitialData userInitData;
    
        @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
        @JoinColumn(name = "id_user")
        private AppUser appUserPerson;
        
        @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
        private List<WeightRecord> weightsList;
        /*Getters and setters*/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM