1

I want to create a many to many relationship with a extra column. I configured this:

@Entity
public class Configuration extends AbstractEntity {

    @OneToMany(
            mappedBy = "configuration",
            cascade=CascadeType.ALL,
            orphanRemoval = true
    )
    @JsonIgnore
    private List<ConfigurationQuestion> configurationQuestions = new ArrayList<>();


    public void addQuestion(QuestionDTO question) {
        ConfigurationQuestion configurationQuestion = new ConfigurationQuestion(this,
                question.getQuestion(), question.getResponse());

        configurationQuestions.add(configurationQuestion);
    }

}

Join table

@Entity
public class ConfigurationQuestion implements Serializable {
    @EmbeddedId
    private ConfigurationQuestionId id ;

    @ManyToOne(fetch = FetchType.LAZY)
    @MapsId("configurationId")
    private Configuration configuration;


    @ManyToOne(fetch = FetchType.EAGER)
    @MapsId("questionId")
    @JoinColumn(name="question_id")
    private Question question;

    private Integer response; 

    public ConfigurationQuestion(Configuration configuration, Question question,
                                 Integer response) {
        this.configuration = configuration;
        this.question = question;
        this.response = response;
        this.id = new ConfigurationQuestionId(configuration.getId(), question.getId());
    }

}

Embedable id

@Embeddable
public class ConfigurationQuestionId implements Serializable {

    private Long configurationId;

    private Long questionId;
}

In question I don't have any mapping I want to do it one directional. My problem is when I try to save something like this. I want to save a configuration that have as question just ids not the entire object, it is saved separatly.

In Question entity I don't have any mapping I want to do it one directional. My problem is when I try to save something like this. I want to save a configuration that has as question/questions just ids not the entire objects, it is saved separately.

Configuration configuration = new Configuration();
Question question = new Question();
question.setId(1L);

configuration.addQuestion(new QuestionDTO(question, 1));

repository.save(configuration);

I receive the following error. I don't want to cascade the changes to Question entity, if I remove Cascade.ALL from Configuration isn't inserting anything in the join table. Can I do this without making a find for questions?

detached entity passed to persist: Question
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Dorin
  • 2,167
  • 4
  • 20
  • 32
  • Possible duplicate of [ManyToMany on itself with AssociationTable with EmbeddedId - Spring-Data-Jpa](https://stackoverflow.com/questions/52757254/manytomany-on-itself-with-associationtable-with-embeddedid-spring-data-jpa) – K.Nicholas Oct 30 '18 at 19:03
  • @K.Nicholas That answer is not even related to the OP's question. – jbx Oct 31 '18 at 11:47
  • Same thing. "How do I work with ManyToMany associations in spring-data-jpa". He wanted a unidirectional answer and that and more is in there. – K.Nicholas Oct 31 '18 at 14:12
  • No it is completely different. The answer you linked was about an entity referring to itself. This is simply about adding a foreign key reference to another *different* entity when you *know its primary key* so you don't want to incur the overheads of querying the entity from the database. – jbx Oct 31 '18 at 23:28
  • Can you give me a hit about how i can avoid firing the database for questions? – Dorin Nov 04 '18 at 18:08

1 Answers1

1

If you don't want to Cascade your changes from the Configuration entity to the Question entity you have to save it separately. The JPA provider is right to complain that the entity passed is still detached. It is still just a plain old java object instance, the JPA EntityManager does not know about it.

Try to save the Question separately first before saving the Configuration entity.

If you already have the Question in the database, know its ID, but want to avoid getting it completely you can use the getReference() method, which returns a proxy for your Entity. There will still be some overhead by the JPA provider to verify the instance exists (it should throw an EntityNotFoundException if it does not exist), but should be more lightweight.

If you are using a Spring Data JpaRepository there is a similar method, awkwardly named getOne() which does essentially the same thing (it calls the EntityManager.getReference()).

jbx
  • 21,365
  • 18
  • 90
  • 144
  • I save Question separately. But when I want to save Configuration I want to have in ConfigurationQuestion questions with only ids like in exemple. There is a question with id = 1 saved in database.When I save Configuration I want to save Configuration and the relationship from ConfigurationQuestion. – Dorin Oct 31 '18 at 04:33
  • That is not what you are doing in your example. You are creating a completely new `Question` and just setting the `id` to `1`, without setting the rest of the fields. JPA can't know that you just want it to take the `id` from the `Question` entity. The model you have is wrong. – jbx Oct 31 '18 at 11:24
  • Can i specify not the persist the Question and just add it in the join table? – Dorin Oct 31 '18 at 11:35
  • I updated the answer, I think this is what you really want to do. Get a reference to the existent `Question` entity without having to actually retrieve it from the database unless you really need to. – jbx Oct 31 '18 at 11:44