在数据库上插入实体+外键的正确方法(使用:Mysql,JPA)
Posted
技术标签:
【中文标题】在数据库上插入实体+外键的正确方法(使用:Mysql,JPA)【英文标题】:Right way to make insertion of an entity + foreign key on database(Use : Mysql, JPA) 【发布时间】:2017-09-17 01:41:00 【问题描述】:我有一个关于在数据库(mysql、JPA)上插入我的实体+外键的正确方法的问题。 在问我的问题之前,我尝试了我找到的解决方案,我花了几天时间自己解决问题。 我相信我有问题:
我需要做的是:
-
我已经在站点表中存在数据(信息)
我必须在序列表中插入新序列
我必须在序列表中插入新序列,并关联FK站点(站点存在,无需再次插入)
主要问题是:
-
当我在序列表中插入时,我得到了带有 FK 位点的序列
正确插入
但是!问题是我也有站点插入
在数据库中,所以每次插入时都会冗余插入站点
序列数据
Jpa 存储库:我首先按名称获取 Site 对象
@覆盖 公共站点 findSiteByName(String Name_Site) 列出站点 = entityManager.createQuery("SELECT s FROM Site s").getResultList(); 对于(网站项目:网站) if (item.getNom_Site().equals(Name_Site)) 归还物品; 返回空值; Jpa方法在数据库中插入序列@Override
public Sequence saveSequence(Sequence sequence)
return super.save(sequence);
我的休息控制器:我的主要课程是:@GET @Path("/addSeq") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public Sequence addSeq(@Context final UriInfo uriInfo) Site site = siteService.findSiteByName("Name_Site"); Sequence sequence = sequenceFactory.CreateSequence(new Date(), new Date(), "", "", "", 4, 6, 10, 12); sequence.setSite(site); site.getSequences().add(sequence); sequenceservice.saveSequence(sequence); return null;
@Entity @Table(name = "Sequences") public class Sequence @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "Id_Sequence", unique = true, nullable = false) private long Id_Sequence; private Date ....; private Date ....; private String ....; private String ....; private String ....; private int ....; private int ....; private double ....; private double ....; @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) private Set<TraceSequence> traceSequences = new HashSet<>(); @ManyToOne(cascade = CascadeType.ALL) private Site site; public constructor... public set.. public get..
@实体 @Table(name = "网站") 公共类站点
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "Id_Site", unique = true, nullable = false)
private long Id_Site;
private String ...;
private boolean ...;
private long ...;
private Date ...;
private Date ...;
private String ...;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<Sequence> sequences = new HashSet<>();
@ManyToOne
private ... ...;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<...> ... = new HashSet<>();
@ManyToOne
private ... ...;
public constructor...
public set..
public get..
【问题讨论】:
super.save(sequence)
后面叫什么?
您能否检查一下Site site = siteService.findSiteByName("Name_Site");
是否提供了具有正确Id_Site
值的站点?
在 super.save(sequence) 后面 ==> JpaSequenceRespository 扩展 BaseJpaRepository
Site site = siteService.findSiteByName("Name_Site") ==> 是的,我检查了它返回的内容,我得到了 Site 的完整对象
你有自己的BaseJpaRepository
还是来自哪里?
【参考方案1】:
您可以尝试删除所有关系中的cascade = CascadeType.ALL
吗?我认为主要问题是CascadeType.PERSIST
级联到子元素。你可以看看这里JPA with JTA: Persist entity and merge cascaded child entities
我建议的另一件事是将表数从 3 减少到 2。由于您使用的是 OneToMany
-relation,它不需要像现在这样的映射表。为了实现这一点,在 OneToMany 注释中使用了 mappedBy 子句,并在 ManyToOne 站点上使用了附加的 JoinColumn 注释。
@Entity
@Table(name = "Sites")
public class Site
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "Id_Site", unique = true, nullable = false)
private long Id_Site;
private String ...;
private boolean ...;
private long ...;
private Date ...;
private Date ...;
private String ...;
@OneToMany(mappedBy="site", fetch = FetchType.EAGER)
private Set<Sequence> sequences = new HashSet<>();
@Entity
@Table(name = "Sequences")
public class Sequence
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "Id_Sequence", unique = true, nullable = false)
private long Id_Sequence;
private Date ....;
private Date ....;
private String ....;
private String ....;
private String ....;
private int ....;
private int ....;
private double ....;
private double ....;
@OneToMany(fetch = FetchType.EAGER)
private Set<Sequence> traceSequences = new HashSet<>();
@ManyToOne(cascade = CascadeType.MERGE)
@JoinColumn(name = "site_Id_Site", nullable = false)
private Site site;
已编辑 我试过了:
public interface SequenceRepository extends JpaRepository<Sequence, Long>
和
Site site = siteRepository.findOne(1L);
Sequence seq = new Sequence();
seq.setSite(site);
site.getSequences().add(seq);
sequenceRepository.save(seq);
带来
Hibernate: select site0_.id_site...
Hibernate: insert into sequences (site_id_site) values (?)
在类路径中我确实有spring-data-rest-webmvc-2.5.6.RELEASE.jar
。
【讨论】:
感谢您的回答, 我昨天更改了代码以使用 CascadeType.MERGE,它只会更新您的网站。 CascadeType.MERGE ==> 给了我同样的错误:org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - 在查询刷新之前保存瞬态实例:com.xxx.xxx.xxx.model。 sequence.Sequence.site -> com.xxx.xxx.xxx.model.site.Site CascadeType.PERSIST ==> 插入站点和序列 我想我找到了问题的根源。我在 Site 表上手动插入了一行,PK 为“0”,当我得到“Site site = siteService.findSiteByName("Name_Site")”==> 我也得到 PR 为“0”(空) ,据我了解,当 PR 等于“0”时,休眠就像插入新实体一样。以上是关于在数据库上插入实体+外键的正确方法(使用:Mysql,JPA)的主要内容,如果未能解决你的问题,请参考以下文章
ssh关于含有外键的传值中无法识别正确的action的原因和解决办法