简体   繁体   English

Spring数据的自定义保存查询(Hibernate JPA)

[英]custom save query for Spring Data (Hibernate JPA)

I have two entities: 我有两个实体:

WeeklyBoxOffice.java WeeklyBoxOffice.java

 @Entity
    public class WeeklyBoxOffice {

    @NotNull
    private String country;

    @Id
    @NotNull
    private String name;

    @NotNull
    private long weeklyGross;

    @NotNull
    private double weeklyChange;

    @OneToOne//(fetch = FetchType.LAZY, cascade=CascadeType.ALL )
    @JoinColumn(name = "name")
    private Movie movie;
    }

Movie.java Movie.java

 @Entity
    @Table(name = "movies")
    public class Movie {

    @Id
    @NotNull
    private String name;

    @NotNull
    private String imageLink;
    }

And following repository: 和以下存储库:

public interface WeeklyBoxOfficeRepository extends   
CrudRepository<WeeklyBoxOffice, String> {
    Iterable<WeeklyBoxOffice> findByCountryOrderByWeeklyGrossDesc(String country);
}

Existing find method works like left join, which is exactly what I need. 现有的find方法的工作方式类似于左连接,这正是我所需要的。 But how to save WeeklyBoxOffice object without saving movie object? 但是,如何在不保存电影对象的情况下保存WeeklyBoxOffice对象呢? I don't really the idea of creating WeeklyBoxOfficeLite. 我真的不是创建WeeklyBoxOfficeLite的想法。 Now it gives an exception 现在它给出了一个例外

org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : entity.WeeklyBoxOffice.movie -> entity.Movie; org.springframework.dao.InvalidDataAccessApiUsageException:org.hibernate.TransientPropertyValueException:对象引用了一个未保存的瞬态实例-在刷新之前保存该瞬态实例: nested exception is java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : entity.WeeklyBoxOffice.movie -> entity.Movie ... Caused by: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : WeeklyBoxOffice.movie -> entity.Movie 嵌套异常是java.lang.IllegalStateException:org.hibernate.TransientPropertyValueException:对象引用了一个未保存的瞬态实例-在刷新之前保存该瞬态实例:entity.WeeklyBoxOffice.movi​​e-> entity.Movie ...原因:org.hibernate.TransientPropertyValueException :对象引用了一个未保存的瞬态实例-在刷新之前保存该瞬态实例:WeeklyBoxOffice.movi​​e-> entity.Movie

Is it possible to use somehow NativeQuery for save method to ignore nested Movie object? 是否可以使用NativeQuery的save方法忽略嵌套的Movie对象?

If you removed the cascade from the association with movie , then you should not get this error, imho... 如果您从与movie的关联中删除了级联,那么应该不会出现此错误,恕我直言。

But anyway maybe this workaround can help... 但是无论如何,这种解决方法可能会有所帮助...

public class WeeklyBoxOfficeService {

    @Autoware
    private WeeklyBoxOfficeRepo repo;

    public WeeklyBoxOffice saveWithoutMovie(WeeklyBoxOffice weeklyBoxOffice) {

        weeklyBoxOffice.setMovie(null); // 'unlink' movie from BO
        repo.save(weeklyBoxOffice); // save BO without movie
    }  
}

@RestController
@RequestMapping("/weeklyBoxOffice")
public class WeeklyBoxOfficeController {

    @Autoware
    private WeeklyBoxOfficeService service;

    @PostMapping
    public ResponseEntity<?> saveWithoutMovie(@RequestBody WeeklyBoxOffice weeklyBoxOffice) {

        WeeklyBoxOffice result = service.saveWithoutMovie(weeklyBoxOffice);
        return ResponseEntity.ok(result);
    }
}

Why not simply set to null the movie field before invoking the save() operation ? 为什么不简单地在调用save()操作之前将movie field设置为null
In this way, Hibernate will ignore it during the flush. 这样,休眠时Hibernate将忽略它。

Use native query update something like this 使用本机查询更新类似这样的内容

 public void updateSample(EntityObj entityObj) {
            sql = "UPDATE Table clm SET clm.status ='"+entityObj.getStatus()+"'";
            sql +=" WHERE clm.id in ("+entityObj.getId()+")";
            Query q = em.createQuery(sql);
            msg  = q.executeUpdate();
    }

OR 要么

remove CascadeType 删除CascadeType

@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "name")
private Movie movie;

I think you are also sending JSON of Movie with WeeklyBoxOffice JSON like 我认为您还使用WeeklyBoxOffice JSON发送电影的JSON,例如

{
    "country": "xxxxxx",
    "name": "xxxxxxxx",
    "weeklyGross": "xxxxx",
    "weeklyChange": "xxxxxx",
    "movie": {
        "name": "xxxxxx",
        "imageLink": "xxxxx"
    }
}

So you have to first create a MovieRepository and save movie using this repository and then save WeeklyBoxOffice using WeeklyBoxOfficeRepository like this 因此,您必须首先创建一个MovieRepository并使用该存储库保存电影,然后使用WeeklyBoxOfficeRepository这样保存WeeklyBoxOffice

    @Autowired
    WeeklyBoxOfficeRepository weeklyBoxOfficeRepository;
    @Autowired
    MovieRepository movieRepository;
    public WeeklyBoxOffice saveWeeklyBoxOffice(WeeklyBoxOffice weeklyBoxOffice) {
           movieRepository.save(weeklyBoxOffice.getMovie());
           return weeklyBoxOfficeRepository.save(weeklyBoxOffice);
    }

Other solution, you can use CascadeType.All for saving this JSON using only one line 其他解决方案,您可以使用CascadeType.All仅使用一行来保存此JSON

weeklyBoxOfficeRepository.save(weeklyBoxOffice);

this line will automatically save and will also assign movie name(id) to weeklyBoxOffice . 此行将自动保存,还将电影名称(id)分配给weeklyBoxOffice

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

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