Использование естественных ключей как части equals и hashCode - PullRequest
3 голосов
/ 24 сентября 2010

Я знаю, что эта тема обсуждалась множество раз, но все же нуждаюсь в некоторых разъяснениях по проблеме, с которой мы сталкиваемся.Лучшие Hibernate практики говорят об использовании естественных ключей для методов equals / hashCode.У нас есть составной ключ, который состоит из 2 параметров (скажем, String name, Organization org), к которым принадлежит конкретный объект.К сожалению, я не могу использовать org, так как он загружен лениво и приводит к другим проблемам, и я не хочу создавать суррогатный ключ (возможно, автоматически сгенерированный из базы данных или UUID, созданный с помощью вызова API до создания объекта).Какие варианты у меня действительно есть, так как в приведенных выше полях Object (name, org) уникальны, и я не могу просто написать свою логику только на основе самого поля name.Является ли суррогатный ключ единственным вариантом, означает ли это, что я должен хранить это значение как часть каждой строки в таблице?

Ответы [ 3 ]

4 голосов
/ 25 сентября 2010

Если вы хотите что-то вроде

public class MyEntity {

    private String name;

    private Organization organization;

    // getter's and setter's

    public boolean equals(Object o) {
        if(!(o instanceof MyEntity))
            return false;

        MyEntity other = (MyEntity) o;
        return new EqualsBuilder().append(getName(), other.getName())
                                  .append(getOrganization(), other.getOrganization())
                                  .isEquals();
    }

}

Но если вы хотите избежать этого, потому что теперь вы хотите загрузить лениво загруженную сущность , вы можете положиться на Hibernate.isInitialized метод и предоставить свою собственную подпрограмму

public boolean equals(Object o) {
    if(!(o instanceof MyEntity))
        return false;

    MyEntity other = (MyEntity) o;
    boolean equals = new EqualsBuilder().append(getName(), other.getName())
                                        .isEquals();

    if(Hibernate.isInitialized(getOrganization())) {
       // loaded Organization
    } else {
       // supply custom routine
    }

    return equals;
}

У меня есть не обновленная веб-страница, где Hibernate предоставляет следующую матрицу

                                        no eq/hC at all  eq/hC with the id property  eq/hC with buisness key
use in a composite-id                   No               Yes                         Yes
multiple new instances in set           Yes              No                          Yes
equal to same object from other session No               Yes                         Yes
collections intact after saving         Yes              No                          Yes        

Где следующие проблемы:

использование в составном идентификаторе :

Чтобы использовать объект в качестве составного идентификатора, он должен каким-то образом реализовать equals / hashCode, == идентичности в этом случае будет недостаточно.

несколько новых экземпляров в наборе :

Будет ли работать следующее или нет:

HashSet someSet = new HashSet();
someSet.add(new PersistentClass());
someSet.add(new PersistentClass());
assert(someSet.size() == 2);

равно тому же объекту из другого сеанса :

Будет ли работать следующее или нет:

PersistentClass p1 = sessionOne.load(PersistentClass.class, new Integer(1));
PersistentClass p2 = sessionTwo.load(PersistentClass.class, new Integer(1));
assert(p1.equals(p2));

коллекции сохраняются после сохранения :

Будет ли работать следующее или нет:

HashSet set = new HashSet();
User u = new User();
set.add(u);
session.save(u);
assert(set.contains(u));

Также выделен этот поток , где широко обсуждается реализация equals / hashCode

2 голосов
/ 24 сентября 2010

В рекомендациях Hibernate говорится об использовании естественных ключей для методов equals / hashCode.

Да, поэтому я не буду подробно останавливаться на этом.

У нас есть составной ключ, который состоит из 2 параметров (скажем, String name, Organization org), для которыхконкретный объект принадлежит.К сожалению, я не могу использовать org, так как он загружен лениво и приводит к другим проблемам.

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

Какие опции у меня действительно есть, так как в приведенных выше полях Object (name, org) уникальны, и я не могу просто написать свою логику только на основе самого поля имени.

Как я уже сказал, предоставление более подробной информации может помочь.Но на всякий случай учтите, что вызов org.getId() на прокси-сервере не должен запускать загрузку сущности, если вы используете тип доступа к свойству , поэтому вы должны иметь возможность использовать это в своемравно реализации.

0 голосов
/ 24 сентября 2010

Как называется объект, имеющий имя и организацию? Я предполагаю, что это называется Foo. Я так понимаю, вы не можете сказать foo.getOrganization (), потому что соединение с базой данных закрыто? Можете ли вы изменить свой FooDAO, чтобы он загружал Организацию, как только foo будет считан из базы данных?

Тогда это будет доступно позже, когда вам нужно будет что-то сделать с помощью equals () и hashCode ().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...