JPA 2.0 Hibernate @OneToMany + @MapKeyJoinColumn - PullRequest
       1

JPA 2.0 Hibernate @OneToMany + @MapKeyJoinColumn

6 голосов
/ 22 февраля 2011

OneToMany + MapKeyJoinColumn не работает для меня, пожалуйста, предложите, что я делаю неправильно.

Я использую JPA 2.0 + Hibernate 3.6.1 И хочу отобразить следующие таблицы:


Question to Statement to Language relationship


На занятия:



@Entity
public class Question {
    // id and other fields

    @OneToMany(mappedBy="question", cascade = CascadeType.ALL)
    @MapKeyJoinColumn(name="language_id")
    private Map<Language, Statement> statements =
        new HashMap<Language, Statement>();
}

@Entity
public class Statement {
    @Id
    private Long id;

    @ManyToOne
    @JoinColumn(name = "language_id", nullable = true)
    private Language language;

    @ManyToOne
    @JoinColumn(name = "question_id", nullable = false)
    private Question question;

    @Column(name = "message")
    private String message;
}

@Entity
public class Language {
    @Id
    private Long id;

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

Но это не работает. EntityManager сохраняет его правильно, но когда я получаю Вопрос, в его карте утверждений есть только одна запись языка в ноль. Пожалуйста, помогите


Edit1 : Странно, но когда я предварительно загружаю все языки, как это:


String sql = "select l from Language l";
List languages = entityManager.createQuery(sql, Language.class).getResultList();

тогда это работает!
Кто-нибудь знает, как заставить hibernate автоматически загружать все объекты определенного класса?

Ответы [ 3 ]

3 голосов
/ 30 августа 2011

Фактически, свойство id в вашем классе Statement должно быть составным первичным ключом. Вам не нужен Statement_id в вашей таблице Statement. Первичный ключ состоит из language_id и question_id.

Попробуйте это:

    @Entity
    public class Statement implements Serializable {

        private static final long serialVersionUID = 1L;

        @EmbeddedId
        private StatementId id = new StatementId();

        @Column(name = "message")
        private String message;
    }

    @Embeddable
    private static class StatementId implements Serializable {

        private static final long serialVersionUID = 1L;

        StatementId(){}

        @ManyToOne
        private Question product;

        @ManyToOne
        private Language language;

    }

И не забывайте fetchType в вопросе, чтобы избежать LazyInitializationExceptions.

public class Question {

    @OneToMany(mappedBy="id.question", fetch=FetchType.EAGER)
    @MapKeyJoinColumn(name="language_id")
    private Map<Language, Statement> statements = new HashMap<Language, Statement>();
}

Надеюсь, это поможет.

1 голос
/ 08 марта 2011

Попробуйте вызвать Statement.size (), чтобы убедиться, что данные извлекаются, или вы можете попытаться определить тип выборки ваших отношений с EAGER: @OneToMany (mappedBy = "question", cascade = CascadeType.ALL, fetch = FetchType.EAGER)

Вы можете прочитать это: http://en.wikibooks.org/wiki/Java_Persistence/Relationships#Eager_Join_Fetching

1 голос
/ 28 февраля 2011

Используете ли вы кэширование второго уровня?Является ли ваш объект уже частью сеанса (кэширование первого уровня)?Попробуйте сделать сеанс clear ()

...