Hibernate @ManyToMany doubts

2

I'm quite a rookie as far as Hibernate is concerned, the fact is that looking at the documentation of the annotation @ManyToMany a question has arisen, which is quite appropriate to my case, and is as follows:

Let's say the case that I am developing a game and I have the tables characters and the table spells, it is logical that a character can use more than one spell, for example "punch" and "kick". And that the same spell can be used by several different characters.

The code of characters would be the following:

@ManyToMany(cascade = { CascadeType.ALL })
    @JoinTable(
        name = "characterSpells", 
        joinColumns = { @JoinColumn(name = "characterId") }, 
        inverseJoinColumns = { @JoinColumn(name = "spellId") }
    )
    List<Spell> spells = new ArrayList<>();

And that of spells the following:

@ManyToMany(mappedBy = "spell")
    private List<Character> characters;

The thing is that I simply would not be interested in saving in each spell the list of characters that use it.

What I think is if this relationship really is @ManyToMany or @OneToMany where @One is Spell and @Many is Characters, or I'm just doing something wrong, or I've understood something wrong.

    
asked by Jordi72 11.08.2018 в 22:40
source

1 answer

0

These fields are mainly required to generate the relationships of underlying entities in JPA, so JPA can make queries and optimizations based on those relationships.

However, as is your case, it is not always necessary to have the references to the entities with which a certain entity is related.

For that there is an attribute of the JPA annotations that indicate relations between entities / tables ( @OneToOne , @ManyToOne , @OneToMany , @ManyToMany ) called fetch , which allows you to specify the way JPA loads u obtains from the database the entities related to an entity.

Fetching of Related Entities

There are two possibilities:

FetchType.LAZY - Delayed (or lazy) upload

It loads all the entities related to an entity at the moment in which the same entity is loaded, it does not matter that you never use them. For example:

@OneToMany(fetch=FetchType.EAGE)

FetchType.EAGER - Early load

Load entities related to an entity ONLY when they are needed, that is, when you refer to that relationship by calling the list. For example:

@OneToMany(fetch=FetchType.LAZY)

It is worth mentioning that the default fetchType for the relations to-One ( @OneToOne , @ManyToOne ) is EAGER and for the relations a-Many ( @OneToMany , @ManyToMany ) is LAZY.

Why is it important? In a single word: Performance. An early load will require an additional query to the database by JPA, which translates into a delay when loading the root entity. On the other hand, a delayed load will make the root entity load faster, but there will be a delay when using the entities related to that entity. Of course, the duration of these delays are almost always milliseconds or less, everything depends on the number of records related to the root entity, perhaps from tens of thousands of records that delay can be perceived.

To give you a direct answer to your question. You must leave the @ManyToMany relationships. However, if you are not going to need to get the characters that use that spell, leave the FetchType in LAZY in the entity% Character relation. Although by default it already has FetchType.LAZY , so you can leave it as it is.

@ManyToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY)
    @JoinTable(
        name = "characterSpells", 
        joinColumns = { @JoinColumn(name = "characterId") }, 
        inverseJoinColumns = { @JoinColumn(name = "spellId") }
    )
    List<Spell> spells = new ArrayList<>();

And for the entity Spell if you must specify to change the FetchType to EAGER. (I guess you'll need to know from the moment you create the Character that Spell s you can use).

@ManyToMany(mappedBy = "spell", fetch = FetchType.EAGER)
    private List<Character> characters;
    
answered by 16.08.2018 / 05:59
source