Hibernate one-to-one: getId () bez pobierania całego obiektu

Chcę pobrać id relacji jeden do jednego bez ładowania całego obiektu. Myślałem, że mogę to zrobić za pomocą leniwego ładowania w następujący sposób:

class Foo { 
    @OneToOne(fetch = FetchType.LAZY, optional = false)
    private Bar bar; 
}


Foo f = session.get(Foo.class, fooId);  // Hibernate fetches Foo 

f.getBar();  // Hibernate fetches full Bar object

f.getBar().getId();  // No further fetch, returns id

Chcę, aby f. getBar () nie uruchamiał kolejne pobieranie. Chcę, aby hibernate dał mi obiekt proxy, który pozwala mi na wywołanie .getId () bez pobierania obiektu Bar.

Co robię źle?
Author: Manuel Drieschmanns, 2010-04-07

9 answers

Użyj strategia dostępu do nieruchomości

Zamiast

@OneToOne(fetch=FetchType.LAZY, optional=false)
private Bar bar;

Użyj

private Bar bar;

@OneToOne(fetch=FetchType.LAZY, optional=false)
public Bar getBar() {
    return this.bar;
}
Teraz działa dobrze!

Proxy jest inicjalizowane, jeśli wywołujesz dowolną metodę , która nie jest metodą getter identyfikatora. Ale to działa tylko przy użyciu strategii dostępu do nieruchomości. Pamiętaj o tym.

Zobacz: Hibernate 5.2 User guide

 34
Author: Arthur Ronald,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-23 18:24:02

Aby dodać do listy: możesz wymusić dostęp do właściwości przez @Access(AccessType.PROPERTY) (lub przestarzałe @AccessType("property")), Zobacz http://256stuff.com/gray/docs/misc/hibernate_lazy_field_access_annotations.shtml

Innym rozwiązaniem może być:

public static Integer getIdDirect(Entity entity) {
    if (entity instanceof HibernateProxy) {
        LazyInitializer lazyInitializer = ((HibernateProxy) entity).getHibernateLazyInitializer();
        if (lazyInitializer.isUninitialized()) {
            return (Integer) lazyInitializer.getIdentifier();
        }
    }
    return entity.getId();
}

Działa również dla jednostek odłączonych.

 24
Author: xmedeko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-11 16:26:04

Add @AccessType ("Właściwość")

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@AccessType("property")
protected Long id;
 10
Author: Dima,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-14 00:59:34

The Java Persistence with Hibernate Book wspomina o tym w "13.1.3 Understanding Proxy":

Tak długo, jak masz dostęp tylko do właściwości database identifier, nie inicjalizacja proxy jest konieczna. (Zauważ, że nie jest to prawda jeśli mapujesz właściwość identyfikatora z bezpośrednim dostępem do pola; Hibernate wtedy nawet nie wie, że metoda getId() istnieje. Jeśli to nazwiesz, proxy musi być zainicjowany.)

Jednak na podstawie odpowiedzi @xmedeko na tej stronie Opracowałem hack, aby uniknąć inicjalizacji proxy , nawet jeśli używasz strategii bezpośredniego dostępu do pola. Po prostu zmień metodę getId(), Jak pokazano poniżej.

Zamiast:

    public long getId() { return id; }

Użycie:

    public final long getId() {
        if (this instanceof HibernateProxy) {
            return (long)((HibernateProxy)this).getHibernateLazyInitializer().getIdentifier();
        }
        else { return id; }
    }

Chodzi o to, aby oznaczyć metodę getId() jako final, Aby proxy nie mogły jej nadpisać. Następnie wywołanie metody nie może uruchomić żadnego kodu proxy, a tym samym nie może zainicjować proxy. Sama metoda sprawdza, czy jej instancja jest proxy i w tym przypadku zwraca id z proxy. Jeśli instancja jest rzeczywistym obiektem, zwraca id.

 7
Author: MarcG,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-15 20:33:54

Niestety przyjęta odpowiedź jest błędna. Również inne odpowiedzi nie dają najprostszego lub jasnego rozwiązania.

Użyj poziomu dostępu właściwości dla ID klasy BAR.

@Entity
public class Bar {

    @Id
    @Access(AccessType.PROPERTY)
    private Long id;

    ...
}

Po prostu takie proste:)

 7
Author: Paul Wasilewski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-09 18:21:16

W org.hibernacja.Sesja masz funkcję, która wykonuje pracę bez leniwego ładowania encji:

Public Serializable getIdentifier (Object object) throws HibernateException;

Znalezione w hibernate 3.3.2.GA :

public Serializable getIdentifier(Object object) throws HibernateException {
        errorIfClosed();
        checkTransactionSynchStatus();
        if ( object instanceof HibernateProxy ) {
            LazyInitializer li = ( (HibernateProxy) object ).getHibernateLazyInitializer();
            if ( li.getSession() != this ) {
                throw new TransientObjectException( "The proxy was not associated with this session" );
            }
            return li.getIdentifier();
        }
        else {
            EntityEntry entry = persistenceContext.getEntry(object);
            if ( entry == null ) {
                throw new TransientObjectException( "The instance was not associated with this session" );
            }
            return entry.getId();
        }
  }
 3
Author: Grégory,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-20 16:21:27

Jest teraz biblioteka typów danych jackson hibernate tutaj:

Https://github.com/FasterXML/jackson-datatype-hibernate

I możesz skonfigurować funkcje:

 Hibernate4Module hibernate4Module = new Hibernate4Module();
 hibernate4Module.configure(Hibernate4Module.Feature.SERIALIZE_IDENTIFIER_FOR_LAZY_NOT_LOADED_OBJECTS, true);

To będzie zawierać id relacji Lazy loaded -

 1
Author: chrismarx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-26 15:27:20

Możesz użyć zapytania HQL. Metoda getBar () zwróci serwer proxy, który nie zostanie pobrany, dopóki nie wywołasz jakiejś metody związanej z danymi. Nie jestem pewien, w czym dokładnie tkwi twój problem. Możesz nam podać więcej informacji?

 0
Author: Bozhidar Batsov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-07 15:33:23

Zmień metodę gettera w następujący sposób:

public Bar getBar() {
    if (bar instanceof HibernateProxy) {
        HibernateProxy hibernateProxy = (HibernateProxy) this.bar;
        LazyInitializer lazyInitializer = hibernateProxy.getHibernateLazyInitializer();
        if (lazyInitializer.getSession() == null)
            bar = new Bar((long) lazyInitializer.getIdentifier());
    }

    return bar;
}
 0
Author: Mohsen Kashi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-12 14:52:53