3

I created classes:

@Table(name = "FILE_SET")
@Entity
public class FileSet
{
    @Id
    @Column(name = "FileSetId")
    private final long fileSetId;

    @Column(name = "FileSetState")
    private final int fileSetState;

    @OneToMany(targetEntity = Variables.class)
    private final Set<Variables> variables;
}

and

@Entity
@Table(name = "VARIABLES")
public class Variables
{
    @Id
    @Column(name = "VariablesId")
    private final int variablesId;

    @ManyToOne(targetEntity = FileSet.class)
    @JoinColumn(name = "CurrentFileSetId")
    private final long currentFileSetId;

    @Column(name = "CurrentDevicesDictId")
    private final long currentDevicesDictId;
}

And this code is crating tables: https://zapodaj.net/b18d0afb396e5.png.html

But I wanted to have only "Variables" and "FileSet", where CurrentFileSetId in Variables is foreign key from FileSet. What am I doing wrong? I'm using hibernate first time.

pustypawel
  • 331
  • 2
  • 17

2 Answers2

2

In OneToMany side add @JoinColumn(name = "CurrentFileSetId")

@OneToMany(targetEntity = Variables.class)
@JoinColumn(name = "CurrentFileSetId")
private final Set<Variables> variables;

so instead of creating a JoinTable it will create a FK.

Above answer is valid for unidirectional association.

So to make the answer complete, that is in case of bidirectional association, following should be the code :

@ManyToOne(targetEntity = FileSet.class)
@JoinColumn(name = "CurrentFileSetId")
private final long currentFileSetId;

and 

@OneToMany(targetEntity = Variables.class, mappedBy = "currentFileSetId") //this is the field name in FileSet class.
private final Set<Variables> variables;

So basically, the annotation @JoinColumn indicates that this entity is the owner of the relationship. Whereas in mappedBy we provide the field that owns the relationship.

eatSleepCode
  • 4,427
  • 7
  • 44
  • 93
1

I think, that @eatSleepCode's answer is the correct one. But I want to introduce a more common Hibernate approach.

You should never to use plain foreign key fields like currentFileSetId — use associations to entities instead. And you don't need to use targetEntity = Variables.class, Hibernate uses it as a default.

@Table(name = "FILE_SET")
@Entity
public class FileSet
{
    @Id
    @Column(name = "FileSetId")
    private final long fileSetId;

    @Column(name = "FileSetState")
    private final int fileSetState;

    @OneToMany(mappedBy = "currentFileSet")
    private final Set<Variables> variables;

}

@Entity
@Table(name = "VARIABLES")
public class Variables
{
    @Id
    @Column(name = "VariablesId")
    private final int variablesId;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "CurrentFileSetId")
    private FileSet currentFileSet;

}

If you don't want to have association to FileSet on the Variables part (still having CurrentFileSetId as a foreign key):

@Table(name = "FILE_SET")
@Entity
public class FileSet
{
    @Id
    @Column(name = "FileSetId")
    private final long fileSetId;

    @Column(name = "FileSetState")
    private final int fileSetState;

    @OneToMany
    @JoinColumn(name = "CurrentFileSetId")
    private final Set<Variables> variables;

}

@Entity
@Table(name = "VARIABLES")
public class Variables
{
    @Id
    @Column(name = "VariablesId")
    private final int variablesId;

}
v.ladynev
  • 19,275
  • 8
  • 46
  • 67
  • thanks, now i understand, but why are you using FetchType lazy? Is that needed? – pustypawel Jul 08 '16 at 07:38
  • @pustypawel By defaults Hibernate will be fetch entirely `FileSet` while you get `Variables`. Hibernate will get it from a session first level cache, of course. But we use such an "everything lazy approach" in our projects to don't get a lot of data by accident. And you will need to have loaded `FileSet` with `Variables` in the rarely situations, as I think. – v.ladynev Jul 08 '16 at 07:45