30
@OneToOne()
@JoinColumn(name="vehicle_id", referencedColumnName="vehicleId")
public Vehicle getVehicle() {
    return vehicle;
}

My UserDetails class has a one-to-one mapping with the Entitity class Vehicle. Hibernate creates the 2 tables and assigns a generic Foreign Key, which maps the vehicle_id column (UserDetails table.) to the primary key vehicleId (Vehicle table).

KEY FKB7C889CEAF42C7A1 (vehicle_id),
CONSTRAINT FKB7C889CEAF42C7A1 FOREIGN KEY (vehicle_id) REFERENCES vehicle (vehicleId)

My question is : how do we change this generated foreign key, into something meaningful, like Fk_userdetails_vehicle for example.

yovan786
  • 633
  • 1
  • 8
  • 19
  • 5
    @Ashok_udhay Since errors with regard to foreign keys usually just result in the name of the foreign key being spit out by the database, naming the keys gives you some context of what the key is for without having to track it down first in your db creation scripts. – Patrick May 22 '14 at 21:25
  • Just for the curious (and probably too obvious to state); Hibernate is known to use table and property names to generate its constraint/foreign key names ([source](https://stackoverflow.com/questions/36766848/how-does-hibernate-generate-foreign-key-constraint-names)); so the seemingly "random" name will actually remain unchanged, unless you actually change your schema. The MD5 step is what renders the final result "not meaningful", or rather "not human-readable". – Janaka Bandara Nov 14 '21 at 07:42

4 Answers4

37

Since JPA 2.1, you can use the @javax.persistence.ForeignKey annotation:

@OneToOne()
@JoinColumn(name="vehicle_id", referencedColumnName="vehicleId", foreignKey=@ForeignKey(name = "Fk_userdetails_vehicle"))
public Vehicle getVehicle() {
    return vehicle;
}

Prior to JPA 2.1, you could use Hibernate’s @org.hibernate.annotations.ForeignKey annotation, but this is now deprecated:

@OneToOne()
@JoinColumn(name="vehicle_id", referencedColumnName="vehicleId")
@ForeignKey(name="Fk_userdetails_vehicle")
public Vehicle getVehicle() {
   return vehicle;
}
Étienne Miret
  • 6,448
  • 5
  • 24
  • 36
28

Also you can use @ForeignKey embedded in @JoinColumn like this:

@JoinColumn(name = "BAR_ID", foreignKey = @ForeignKey(name = FK_BAR_OF_FOO))

for @ManyToMany relations you can use foreignKey and inverseForeignKey embedded in @JoinTable like this:

@JoinTable(name = "ARC_EMPLOYEE_OF_BAR"
        , joinColumns = {@JoinColumn(name = "BAR_ID")}
        , inverseJoinColumns = {@JoinColumn(name = "EMPLOYEE_ID")}
        , uniqueConstraints = {@UniqueConstraint(name = "ARC_UK_EMPLOYEE_OF_BAR", columnNames = {"EMPLOYEE_ID", "BAR_ID"})}
        , foreignKey = @ForeignKey(name = "ARC_FK_BAR_OF_EMPLOYEE")
        , inverseForeignKey = @ForeignKey(name = "ARC_FK_EMPLOYEE_OF_BAR"))
Nik Kashi
  • 4,447
  • 3
  • 40
  • 63
1

You can do it also by implementing ImplicitNamingStrategy.determineForeignKeyName and using

configuration.setImplicitNamingStrategy(
    new MyImplicitNamingStrategy())

which is nice as you don't have to do it manually again and again. However, it may be hard to put the relevant information there. I tried to concat everything I got (using three underscore to separate the parts) and ended up with

FK_ACCESS_TEMPLATE____TEMPLATE____TEMPLATE_ID____TEMPLATE_ID__INDEX_B

which isn't really better than

FKG2JM5OO91HT64EWUACF7TJCFN_INDEX_B

I guess, using just the referenced table and column names together with a number for uniqueness would be just fine.


Note also that this seems to be legacy Hibernate stuff, unsupported by JPA.

OTOH it works with Hibernate 5.0.1 (just one week old).

maaartinus
  • 44,714
  • 32
  • 161
  • 320
-2

May be you should try this, adding @ForeignKey annotation :

@ManyToOne
@ForeignKey(name="FK_some_model")
@JoinColumn(name="some_model_id")
private SomeModel someModel
Wayan Wiprayoga
  • 4,472
  • 4
  • 20
  • 30