带共享主键的Hibernate @OneToOne(双向)。从属实体不在DB中持久化。 [英] Hibernate @OneToOne with Shared Primary Key(bidirectional). Dependent entity not persisted in DB.

查看:150
本文介绍了带共享主键的Hibernate @OneToOne(双向)。从属实体不在DB中持久化。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个实体PointOfInterest(从这里称为POI)和它的地址。我想用POI作为所有者实体在两者之间定义具有共享主键的一对一双向映射。我使用postgreSQL DB,POI表POIId作为PK,由DB中定义的序列生成器生成。地址表的列POIId是地址表的PK,也是POI表的POIId列的FK以及其它自己的列。

  ** PointOfInterest.java ** 

@实体
@表(名称= \POI \))
public class PointOfInterest implements Serializable {
private static final long serialVersionUID = -5406785879200149642L;

@Id
@Column(name =\POIId \,nullable = false)
@GeneratedValue(strategy = GenerationType.SEQUENCE,generator =poi_seq_poiid_generator )
@SequenceGenerator(name =poi_seq_poiid_generator,sequenceName =poi_seq_poiid,allocationSize = 1)
private long poiId;

@OneToOne(mappedBy =poi,cascade = CascadeType.PERSIST)
私有地址;

//其他字段

------------------------------ -----------------------------------
** Address.java **
@Entity
@Table(name =\Address \)
public class Address implements Serializable {

private static final long serialVersionUID = -7146133528411371107L;

@Id
@GeneratedValue(generator =sharedPrimaryKeyGenerator)
@GenericGenerator(name =sharedPrimaryKeyGenerator,strategy =foreign,parameters = @Parameter(name = property),value =poi))
@Column(name =\POIId \)
private Long poiId;

@OneToOne
@PrimaryKeyJoinColumn
私人PointOfInterest poi;

使用session.saveOrUpdate(poi)保存POI对象之前。我实例化并设置POI对象的所有其他属性。然后,从我的逻辑中的一个单独的方法获取地址对象,并执行类似操作。

  PointOfInterest poi = methodCallToGetPOI(); 
地址address = methodCallToGetAddress();

poi.setAddress(address);
address.setPOI(poi);

//将POI对象发送到数据库层到适当的方法:

session.saveOrUpdate(poi);
session.flush();

当我看到生成的查询时,我看到如下所示:

  Hibernate:
select
nextval('poi_seq_poiid')

Hibernate:
insert

POI
(CreatedBy,CreatedTime,LocationGeographic,ModifiedBy,ModifiedTime,Name,POICode,Radius,POIType ,POIId)

(?,?,?,?,?,?,?,?,?)

所以,显然hibernate并没有在地址表中插入语句。我在网上随处搜索,比较我的映射,他们似乎是正确的。但是,地址表中没有插入行。当我调试流程时,我发现地址对象正在实例化和填充。请帮我弄清楚为什么是这样。我能想到的唯一原因是我使用了序列生成器,并且在互联网上的所有示例和代码片段中,每个人都使用了hibernate的自动生成策略,所以,是不是因为这个原因?我无法使用自动密钥,只能使用我的DB序列。如果这些注释不起作用,请提供一些替代方案。



我使用Spring和Hibernate搭配Spring框架版本4.0.5.RELEASE和一个从org获得的会话工厂.springframework.orm.hibernate4.LocalSessionFactoryBean和事务管理器从org.springframework.orm.hibernate4.HibernateTransactionManager获得。

解决方案

你不用也不想在地址上生成PK(即使是一个特殊的生成器)。

由于这两个实体共享PK,所以这一代可能只发生一次。然后,映射必须负责以相同的值填充 POI_ID ADDRESS_ID



奇怪的是, @PrimaryKeyJoinColumn 在Hibernate 5.2.2上不起作用,但是这里是一个等价的映射:

  @Entity 
@Table(name =POI)
public class PointOfInterest实现Serializable
{
private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,generator =poi_seq_poiid_generator)
@SequenceGenerator(name =poi_seq_poiid_generator,sequenceName =poi_seq_poiid,allocationSize = 1)
@Column(name =POI_ID)
私人长ID;

@OneToOne(mappedBy =poi,cascade = CascadeType.ALL,orphanRemoval = true)
私有地址;

@Column
私人字符串名称;


}

@Entity
@Table(name =Address)
public class Address实现Serializable
{
private static final long serialVersionUID = 1L;

@Id
@OneToOne
@JoinColumn(name =ADDRESS_ID)
private PointOfInterest poi;

@Column
私人字符串名称;


}

使用Hibernate DDL代,这是由此产生的SQL:

  create table地址(name varchar(255),ADDRESS_ID bigint not null,主键(ADDRESS_ID) )ENGINE = InnoDB 
创建表POI(POI_ID bigint不为空,名称varchar(255),主键(POI_ID))ENGINE = InnoDB
alter table地址添加约束FK_Address_ADDRESS_ID外键(ADDRESS_ID)引用POI POI_ID)


I have two entities PointOfInterest (referred as POI from here on) and its Address. I want to define a one to one bidirectional mapping with shared primary key between the two, with POI as owner entity. I am using postgreSQL DB, POI table has POIId as PK, generated by a sequence generator defined in DB. Address table has column POIId which is the PK of Address table and also a FK to POI table's POIId column, along with other columns of its own.

**PointOfInterest.java**

@Entity
@Table(name = "\"POI\"")
public class PointOfInterest  implements Serializable {
    private static final long serialVersionUID = -5406785879200149642L;

    @Id
    @Column(name="\"POIId\"", nullable=false)
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="poi_seq_poiid_generator")
    @SequenceGenerator(name = "poi_seq_poiid_generator", sequenceName = "poi_seq_poiid", allocationSize=1)
    private Long poiId;

    @OneToOne(mappedBy = "poi",cascade = CascadeType.PERSIST)
    private Address address;

    //Other fields

-----------------------------------------------------------------
    **Address.java**
    @Entity
    @Table(name="\"Address\"")
    public class Address implements Serializable{

        private static final long serialVersionUID = -7146133528411371107L;

        @Id
        @GeneratedValue(generator="sharedPrimaryKeyGenerator")
        @GenericGenerator(name="sharedPrimaryKeyGenerator",strategy="foreign",parameters =  @Parameter(name="property", value="poi"))
        @Column(name="\"POIId\"")
        private Long poiId;

       @OneToOne
       @PrimaryKeyJoinColumn
       private PointOfInterest poi;

Before saving the POI object using session.saveOrUpdate(poi). I instantiate and set all other properties of POI object. Then, obtain Address object from a separate method in my logic and do something like.

PointOfInterest poi = methodCallToGetPOI();
Address address = methodCallToGetAddress();

poi.setAddress(address);
address.setPOI(poi);

//Send POI object to DB layer to an appropriate method which does:

session.saveOrUpdate(poi);
session.flush();

When I see the query generated, I see something like this:

   Hibernate: 
   select
        nextval ('poi_seq_poiid')

 Hibernate: 
     insert 
     into
         "POI"
         ("CreatedBy", "CreatedTime", "LocationGeographic", "ModifiedBy", "ModifiedTime", "Name", "POICode", "Radius", "POIType", "POIId") 
     values
         (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

So, clearly hibernate is not making an insert statement in Address Table. I have searched everywhere on the internet and compared my mappings, they seem to be correct. However, no row is being inserted in the address table. When I debug the flow, I found that the address object is being instantiated and populated. Please help me figure out why is this. The only reason I can think of this that I am using a sequence generator and in all the examples and code snippets on the internet everybody has used hibernate's auto generation strategy, so, is it because of this? I cannot use auto gen key, I have to use my DB sequence only. If these annotations won't work, kindly suggest some alternative.

I am using Spring and Hibernate with spring framework version 4.0.5.RELEASE and a session factory obtained from org.springframework.orm.hibernate4.LocalSessionFactoryBean and transaction manager obtained from org.springframework.orm.hibernate4.HibernateTransactionManager.

解决方案

you don't want to generate the PK on Address too (even with an ad-hoc generator).

Since these two entities share the PK, the generation may happen only once. Then the mapping have to be responsible to populate both POI_ID and ADDRESS_ID with the same value.

Strange thing, @PrimaryKeyJoinColumn does not work anymore on Hibernate 5.2.2, but here is an equivalent mapping:

@Entity
@Table(name = "POI")
public class PointOfInterest implements Serializable
{
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "poi_seq_poiid_generator")
    @SequenceGenerator(name = "poi_seq_poiid_generator", sequenceName = "poi_seq_poiid", allocationSize = 1)
    @Column(name = "POI_ID")
    private Long id;

    @OneToOne(mappedBy = "poi", cascade = CascadeType.ALL, orphanRemoval = true)
    private Address address;

    @Column
    private String name;

    ...
}

@Entity
@Table(name = "Address")
public class Address implements Serializable
{
    private static final long serialVersionUID = 1L;

    @Id
    @OneToOne
    @JoinColumn(name = "ADDRESS_ID")
    private PointOfInterest poi;

    @Column
    private String name;

    ...
}

Using Hibernate DDL generation, this is the resulting SQL:

create table Address (name varchar(255), ADDRESS_ID bigint not null, primary key (ADDRESS_ID)) ENGINE=InnoDB
create table POI (POI_ID bigint not null, name varchar(255), primary key (POI_ID)) ENGINE=InnoDB
alter table Address add constraint FK_Address_ADDRESS_ID foreign key (ADDRESS_ID) references POI (POI_ID)

这篇关于带共享主键的Hibernate @OneToOne(双向)。从属实体不在DB中持久化。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆