Java JPA:外键也是主键映射

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27305950/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 04:08:49  来源:igfitidea点击:

JPA: Foreign key that is also a primary key mapping

javadatabasejpaorm

提问by Joro Seksa

I have been trying to solve this for whole day but no luck! Also i tried to read most of the tutorials on the net but as you all know they all are full of useless examples that do not reflect what you need in the real world.

我一整天都在试图解决这个问题,但没有运气!此外,我尝试阅读网上的大部分教程,但众所周知,它们都充满了无用的示例,无法反映您在现实世界中的需求。

So here is my situation:

所以这是我的情况:

The database:

数据库:

table: vehicles(vehicleId, brand, model, devYear, regNumber) <-- vehicleId is the PrimaryKey

表:车辆(vehicleId、品牌、型号、devYear、regNumber)<-- VehicleId 是主键

table: extras(vehicleId, allowSmoke, allowFood, allowDrinks, airConditioner) <-- vehicleId is a PK and a FK.

表:附加项(vehicleId、allowSmoke、allowFood、allowDrinks、airConditioner)<-- VehicleId 是 PK 和 FK。

The point is that if i have a class Vehicleand a class TravelExtraswhich are mapped to the database i want the Vehicleclass to have an attribute TravelExtrastravelExtras and get and set methods.

关键是,如果我有一个类Vehicle和一个TravelExtras类映射到数据库,我希望Vehicle类具有一个属性TravelExtrastravelExtras 以及 get 和 set 方法。

Unfortunatelly no matter what i tried when i try to persist the object in the databse i get various errors.

不幸的是,无论我尝试将对象保存在数据库中时尝试了什么,我都会遇到各种错误。

Here is an illustration:

这是一个插图:

        EntityManagerFactory emfactory = Persistence.createEntityManagerFactory( "NaStopPU" );
        EntityManager entitymanager = emfactory.createEntityManager( );
        entitymanager.getTransaction( ).begin( );


        TravelExtra travelExtra = new TravelExtra();


        entitymanager.persist(travelExtra);


        Vehicle vehicle = new Vehicle(2L, "10152487958556242", "Mazda", "626", "334343", 2005, 4);  
        vehicle.setTravelExtra(travelExtra);

        entitymanager.persist(vehicle);



        entitymanager.getTransaction().commit();
        entitymanager.close( );

        emfactory.close( );

Any one knows what kind of annotations to use for this One to one case ?

任何人都知道这种一对一案例使用什么样的注释?

回答by Chris Rice

The Java Persistence wikibook has a section called Primary Keys through OneToOne and ManyToOne Relationshipswhich seems to indicate that what you want is possible.

Java Persistence wikibook 有一个名为Primary Keys through OneToOne 和 ManyToOne 关系的部分,这似乎表明您想要的是可能的。

If I'm reading it right, for your case, it would look something like:

如果我没看错,对于你的情况,它看起来像:

class Vehicle {
    @Id
    @Column(name = "EXTRAS_ID")
    private long extrasId;

    @OneToOne(mappedBy="vehicle", cascade=CascadeType.ALL)
    private TravelExtra extras;
}

class TravelExtras {
    @Id
    @Column(name = "VEHICLE_ID")
    private long vehicleId;

    @OneToOne
    @PrimaryKeyJoinColumn(name="VEHICLE_ID", referencedColumnName="EXTRAS_ID")
    private Vehicle vehicle;

    public TravelExtras(Vehicle vehicle) {
        this.vehicleId = vehicle.getId();
        this.vehicle = vehicle;
    }
}

Note that one of your entities will need to make sure it has the same id as the other, which is accomplished in the example by the TravelExtras constructor requiring the Vehicle it is bound to.

请注意,您的一个实体需要确保它与另一个实体具有相同的 id,这在示例中由 TravelExtras 构造函数完成,需要它绑定到的 Vehicle。

回答by hiimjames

You can map your classes for example with Netbeans. It will generate annotations. The problem could be your dao layer. You have to persist objects in correct way. For example can't save travelExtra without Vehicle. Also be aware of owning side.

例如,您可以使用 Netbeans 映射您的类。它将生成注释。问题可能出在你的 dao 层上。您必须以正确的方式持久化对象。例如,不能在没有 Vehicle 的情况下保存 travelExtra。还要注意拥有方。

回答by Felipe Le?o

Why don't you use an @Embeddedobject? When using an embedded object, you get the logical separation you desire in your code and keep your database compliant with Entity-Relational Normalization rules.

为什么不使用@Embedded对象?使用嵌入对象时,您可以在代码中获得所需的逻辑分离,并使数据库符合实体关系规范化规则。

It's weird to think on a One-to-One relationship, because even though JPA/Hibernate allows it, all data should be stored in the same table, making you model simpler, while also simplifying queries and increasing database performance by removing the need for a Join operation.

考虑一对一的关系是很奇怪的,因为即使 JPA/Hibernate 允许它,所有数据都应该存储在同一个表中,使您的建模更简单,同时还简化查询并通过消除对数据库的需求来提高数据库性能加入操作。

When using Embedded objects you don't have to worry about mapping IDs and bizarre relations, since your ORM is capable of understanding that your just making a code separation, instead of demanding an actual relation of One-to-One between tables.

使用嵌入式对象时,您不必担心映射 ID 和奇怪的关系,因为您的 ORM 能够理解您只是在进行代码分离,而不是要求表之间存在一对一的实际关系。

class Vehicle {
    @Id
    @Column(name = "ID")
    private long vehicleId; 
    @Column(name = "BRAND")
    private String brand; 
    @Column(name = "MODEL")
    private String model;
    @Column(name = "DEV_YEAR")
    private int devYear;
    @Column(name = "REG_NUMBER")
    private int regNumber;

    @Embedded
    private TravelExtra extras;

    // Constructor, getters and setters...

}

.

.

@Embeddable
class TravelExtras {

    @Column(name = "ALLOW_SMOKE")
    private boolean allowSmoke; 
    @Column(name = "ALLOW_FOOD")
    private boolean allowFood;
    @Column(name = "ALLOW_DRINKS")
    private boolean allowDrinks;
    @Column(name = "AIR_CONDITIONER")
    private boolean airConditioner;

    // Default Constructor, getters and setters...
}

回答by Sendi_t

I know this is very old qs, but for completeness of your case you can just have (jpa 2.0)

我知道这是非常古老的 qs,但是为了您的案例的完整性,您可以只拥有(jpa 2.0)

@Entity
@Data
public class Vehicle implements Serializable{
   @Id
   @GeneratedValue
   private long vehicleId;
   .. //other props
}

@Entity
@Data
public class VehicleExtras implements Serializable{
         @Id
         @OneToOne (cascade = CASCADE.ALL)
         @MapsId
         @JoinColumn(name ="vehicleId")
         private Vehicle vehicle;

         @Column  
         private boolean allowSmoke; 
         ..// other props.
}

should share same pk/fk for VehicleExtra table

应该为 VehicleExtra 表共享相同的 pk/fk