M
M
Maxim2016-05-10 22:03:39
Java
Maxim, 2016-05-10 22:03:39

How to add an element with a foreign key to the database (hibernate) without selecting an object for it (by id)?

Let's say there are two Entities linked by a foreign key:

@Entity
@Table(name = "a")
public class AEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name", nullable = false)
    private String name;
}

@Entity
@Table(name = "b")
public class BEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "a_id", nullable = false)
    private AEntity a;

    @Column(name = "name", nullable = false)
    private String name;
}

A request comes from the frontend to insert a new record B, of course, the name and id of the element from A comes in it, and not the element itself.
How to correctly insert into the database, without filling in the BEntity.a field, but by its id?
For it seems to me that at first to select the necessary record from the table a, then to insert the record into the table b is a bad decision.

Answer the question

In order to leave comments, you need to log in

2 answer(s)
G
guras256, 2016-05-10
@z17

I do not know of a "legal" way, and it is unlikely that there is one. the meaning of Jpa is that you work in the object model, and not with sql queries.
you can send a request from the frontend in the form:

{
  "name": "some name",
  "a": {
    "id": 1
  }
}

and everything will work
well, I also recommend making the connection unidirectional, that is, put it in A
@JsonIgnore
    @OneToMany(mappedBy = "a")
    private List<BEntity> bs;

generally depends on the goals and needs.
If you want to get exactly id, then you just use the tool for other purposes, take myBatis and write sql.
And if you want to be stubborn, put a transient field in the BEntity class and transfer from it to AEntity -_- :
@Entity
@Table(name = "b")
public class BEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "a_id", nullable = false)
    @JsonIgnore
    private AEntity a;

    @Transient
    private Long aEntityId;

    @Column(name = "name", nullable = false)
    private String name;
}

// получаешь ответ с фронденда:
BEntity b = getBEntity();
// Создаешь AEntity
AEntity a = new AEntity();
// запихиваешь в нее нужный id из транзаент поля
a.setId(b.getAEntityId());
//засовываешь А в Б
b.setA(a);
// можно сохранять

but this is an option from the category of idiocy
in general, ask if you have any more questions

A
Alexander Kosarev, 2016-05-11
@jaxtr

If you don't have save cascading for BEntity.a, then it will be enough for you to initialize an object of the AEntity class with the specified id, nothing more is required for linking.
As an option, add the aId field to BEntity, and make BEntity.a non-modifiable:

@Column(nullable = false)
    private Long aId;

    @ManyToOne
    @JoinColumn(name = "a_id", nullable = false, insertable = false, updatable = false)
    private AEntity a;

In this case, you can add a link without filling in the field. The linked one will be loaded from the database when requested, but will not change when saved, although this is easily solved by assigning a new aId value in the a.
But IMHO, if this is all done in the context of REST services, then the AEntity class object in the BEntity class object must be completely filled.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question