hibernate和mapBy:是否可以在不设置对象之间的双向关系的情况下自动设置外键? [英] hibernate and mappedBy: Is it possible to automatically set foreign key without setting bidirectional relationship among objects?

查看:43
本文介绍了hibernate和mapBy:是否可以在不设置对象之间的双向关系的情况下自动设置外键?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

欢迎

我有2个班级:对话和问题.一次对话有很多问题.

I have 2 classes: Conversation and Question. One Conversation have many questions.

Conversation.java:

Conversation.java:

package com.jcg.jpa.mappedBy;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "CONVERSATION_TABLE")
public class Conversation implements Serializable {

private static final long serialVersionUID = 1L;

@Id
@Column(name = "CONV_ID")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int conversationId;

@Column(name = "CONV_NAME")
private String name;

@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy="conversation")
private Collection<Question> questions = new ArrayList<Question>();

public Conversation() { }

public int getConversationId() {
    return conversationId;
}

public void setConversationId(int conversationId) {
    this.conversationId = conversationId;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public Collection<Question> getQuestions() {
    return questions;
}

public void setQuestions(Collection<Question> questions) {
    this.questions = questions;
}

@Override
public String toString() {
    return "Employee [conversationId=" + conversationId + ", name=" + name + "]";
}
}

Question.java:

Question.java:

package com.jcg.jpa.mappedBy;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = "QUESTION_TABLE")
public class Question implements Serializable {

private static final long serialVersionUID = 1L;

@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;

@ManyToOne
@JoinColumn(name = "CONVERSATION_CONV_ID", nullable = false)
private Conversation conversation;


@Column(name = "QUESTION_TEXT")
private String questionText;

@Column(name = "ANSWER_TEXT")
private String answerText;



public Question() { }

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public String getQuestionText() {
    return questionText;
}

public void setQuestionText(String questionText) {
    this.questionText = questionText;
}

public String getAnswerText() {
    return answerText;
}

public void setAnswerText(String answerText) {
    this.answerText = answerText;
}

public Conversation getConversation() {
    return conversation;
}

public void setConversation(Conversation conversation) {
    this.conversation = conversation;
}

@Override
public String toString() {
    return "Question [id=" + id +  ", questionText=" + questionText
            + ", answerText=" + answerText +"]";
}
}

persistence.xml:

persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="JPAMappedbyExample" transaction-type="RESOURCE_LOCAL">
    <class>com.jcg.jpa.mappedBy.Conversation</class>
    <class>com.jcg.jpa.mappedBy.Question</class>

    <!-- Configuring The Database Connection Details -->
    <properties>
        <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
        <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/jpatest" />
        <property name="javax.persistence.jdbc.user" value="root" />
        <property name="javax.persistence.jdbc.password" value="qwerty" />

    </properties>
</persistence-unit>

现在在Main.java中,我试图创建带有两个问题的对话:

And now in Main.java I'm trying to create Conversation with two questions:

package com.jcg.jpa.mappedBy;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class Main {

private static final EntityManagerFactory emFactoryObj;
private static final String PERSISTENCE_UNIT_NAME = "JPAMappedbyExample";   

static {
    emFactoryObj = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
}

// This Method Is Used To Retrieve The 'EntityManager' Object
public static EntityManager getEntityManager() {
    return emFactoryObj.createEntityManager();
}

private static void insertRecords() {
    EntityManager entityMgrObj = getEntityManager();
    if (null != entityMgrObj) {
        entityMgrObj.getTransaction().begin();

        Conversation conv = new Conversation();
        conv.setName("Discussion about something");

        Question question1 = new Question();
        question1.setQuestionText("2 plus 2");
        question1.setAnswerText("four");
        question1.setConversation(conv);

        Question question2 = new Question();
        question2.setQuestionText("what is Your name");
        question2.setAnswerText("Adam");
        question2.setConversation(conv);

        List<Question> questions = new ArrayList<Question>();
        questions.add(question1);
        questions.add(question2);
        conv.setQuestions(questions);

        entityMgrObj.persist(conv);
        entityMgrObj.getTransaction().commit();

        entityMgrObj.clear();
        System.out.println("Record Successfully Inserted In The Database");
    }
}



public static void main(String[] args) {
    insertRecords();

}
}

在insertRecords()中,我正在创建转换和两个问题.每个问题都引发了对话:

In insertRecords() I'm creating conv and two questions. each of questions has set conversation:

question1.setConversation(conv);
question2.setConversation(conv);

接下来,创建一个包含这两个问题的问题列表并设置为转化问题列表:

Next, a question list which contains these 2 questions is created and set to conv questions list:

conv.setQuestions(questions); 

可以正常工作,因为数据已插入两个表中,并填充了外键CONVERSATION_CONV_ID:

An it is working ok, because data is inserted into both tables, and foreign key CONVERSATION_CONV_ID is filled:

但是,当我删除问题,行中的对话时,

However when I remove setting conversation in questions, lines:

question1.setConversation(conv);
question2.setConversation(conv);

外键设置为NULL.为什么?我们已经在对话问题列表中添加了两个问题:

foreign key is set to NULL. Why? We already added two questions to conversation questions list:

@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy="conversation")
private Collection<Question> questions = new ArrayList<Question>();

,因此休眠状态应该知道什么是这两个问题的对话外键(因为它们位于指定的对话问题列表中).因此,可以避免为每个问题设置对话",而仅将问题添加到对话"的问题列表中吗?我应该如何配置实体来做到这一点?也许这是不可能的,而我们总是需要同时设置两个方向?

, so hibernate should know what is conversation foreign key for these two questions (because they are located on specified conversation questions list). So is it possible to avoid setting Conversation for each of the questions and only add questions to Conversation's question list ? How should I configure entities to do that? Or maybe it's impossible and we always need to set it both directions?

推荐答案

因此,休眠模式应该知道这两个问题的会话外键是什么(因为它们位于指定的会话问题列表中).

so hibernate should know what is conversation foreign key for these two questions (because they are located on specified conversation questions list).

如果您没有使用 setConversation()指定Hibernate,则Hibernate不应不知道这两个 Questions Conversation 是什么,因为它在这里处理对象,并且这两个 questions 都没有任何迹象表明它们属于哪个 Conversation .

No Hibernate shouldn't know what is the Conversation of these two Questions if you don't specify it using setConversation(), because it's dealing with objects here, and these two questions doesn't have any indication on which Conversation they are part of.

说明:

因为当您仅将这两个 questions 添加到 Conversation 对象中时,此信息将不会在 Questions 对象中可见.

Because when you only add these two questions to the Conversation object, this information won't be visible in the Questions objects.

这里的另一件事, mappedBy 属性指示 object 是映射的所有者,因此如果 mappedBy 端?

Another thing here, the mappedBy attribute is indicating wich object is the owner of the mapping, so how can the mapping be made if there's no given object in the mappedBy side?

这就是为什么应该在 Question 对象中指定 Conversation 的原因,以便 Hibernate 可以正确地评估映射.

That's why you should specify the Conversation in Question object, so the mapping can be correctly evaluated by Hibernate.

注意:

建议将 Set 用于 OneToMany 映射,而不要使用任何其他 Collection ,因为此集合不应有任何重复项,因此您最好将其更改为:

It's recommended to use a Set for OneToMany mapping rather than any other Collection, because this collection shouldn't have any duplicates, so you better change it to:

@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy="conversation")
private Set<Question> questions = new HashSet<Question>();

这篇关于hibernate和mapBy:是否可以在不设置对象之间的双向关系的情况下自动设置外键?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆