A proxy is a substitute entity object that carries an identifier while deferring database access. In JPA, EntityManager.getReference() can return this hollow placeholder instead of executing a SELECT. section 10.2.4 section 12.1.1
A Hibernate proxy behaves as follows:
- Keeps the entity in the persistence context without loading its state; PersistenceUnitUtil.isLoaded() and Hibernate.isInitialized() detect this condition. section 10.2.4 section 12.1.1
- Initializes on access to ordinary methods such as getName(), issuing a SELECT; an identifier getter can avoid initialization when the identifier is field-mapped appropriately. section 10.2.4 section 12.1.1
- Fails with LazyInitializationException when detached before initialization, because data cannot be loaded after the persistence context closes. section 10.2.4
- Represents a runtime-generated subclass, so item.getClass() differs from Item.class and proxy-aware type inspection is required. section 12.1.1
- Allows relationships to load incrementally when associations and collections use lazy fetching, rather than loading the entire entity graph immediately. section 12.1 section 12.1.1
Persisting a relationship without loading referenced rows
Item item = em.getReference(Item.class, ITEM_ID); User user = em.getReference(User.class, USER_ID); Bid bid = new Bid(new BigDecimal("99.00")); bid.setItem(item); bid.setBidder(user); em.persist(bid); This procedure uses the identifiers carried by both proxies and performs the INSERT without preceding SELECT statements. section 12.1.1
Hibernate can initialize a proxy explicitly with Hibernate.initialize(). If the represented row has disappeared, initialization raises EntityNotFoundException. Entity classes must permit proxy generation: they require a public or protected no-argument constructor and non-final classes and methods. section 10.2.4 section 12.1.1
Path: Ch12/proxy/src/test/java/com/manning/javapersistence/ch12/proxy /LazyProxyCollections.java Hibernate.initialize(item); #1 // select * from ITEM where ID = ? assertFalse(Hibernate.isInitialized(item.getSeller())); #2 Hibernate.initialize(item.getSeller()); #3 // select * from USERS where ID = ? #1 The first call hits the database and loads the <kbd>Item</kbd> data, populating the proxy with the item’s name, price, and so on. #2 Make sure the <kbd>@ManyToOne</kbd> default of <kbd>EAGER</kbd> has been overridden with <kbd>LAZY</kbd>. That is why the <kbd>seller</kbd> of the <kbd>item</kbd> is not yet initialized. #3 By initializing the <kbd>seller</kbd> of the <kbd>item,</kbd> we hit the database and load the <kbd>User</kbd> data.
Use the executable listing to trace explicit initialization of an Item proxy and its lazy seller association, including the resulting SELECT statements. section 12.1.1


