HHH-7457
enabled hibernate to reattach a collection that hasnt been loaded to the session. note: this can cause data to be loaded outside a transaction. use with caution.
This commit is contained in:
parent
a385792178
commit
a1c9ed7756
|
@ -592,4 +592,6 @@ public interface AvailableSettings {
|
|||
public static final String MULTI_TENANT_IDENTIFIER_RESOLVER = "hibernate.tenant_identifier_resolver";
|
||||
|
||||
public static final String FORCE_DISCRIMINATOR_IN_SELECTS_BY_DEFAULT = "hibernate.discriminator.force_in_select";
|
||||
|
||||
public static final String ENABLE_LAZY_LOAD_NO_TRANS = "hibernate.enable_lazy_load_no_trans";
|
||||
}
|
||||
|
|
|
@ -24,24 +24,17 @@
|
|||
package org.hibernate.collection.internal;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.*;
|
||||
|
||||
import org.hibernate.AssertionFailure;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.LazyInitializationException;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.collection.spi.PersistentCollection;
|
||||
import org.hibernate.engine.internal.ForeignKeys;
|
||||
import org.hibernate.engine.spi.CollectionEntry;
|
||||
import org.hibernate.engine.spi.EntityEntry;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.engine.spi.Status;
|
||||
import org.hibernate.engine.spi.TypedValue;
|
||||
import org.hibernate.engine.spi.*;
|
||||
import org.hibernate.internal.SessionFactoryRegistry;
|
||||
import org.hibernate.internal.util.MarkerObject;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.internal.util.collections.EmptyIterator;
|
||||
|
@ -51,6 +44,8 @@ import org.hibernate.persister.entity.EntityPersister;
|
|||
import org.hibernate.pretty.MessageHelper;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
import javax.naming.NamingException;
|
||||
|
||||
/**
|
||||
* Base class implementing {@link org.hibernate.collection.spi.PersistentCollection}
|
||||
*
|
||||
|
@ -73,6 +68,9 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
private boolean dirty;
|
||||
private Serializable storedSnapshot;
|
||||
|
||||
private String sessionFactoryUuid;
|
||||
private boolean specjLazyLoad = false;
|
||||
|
||||
public final String getRole() {
|
||||
return role;
|
||||
}
|
||||
|
@ -123,6 +121,11 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
return true;
|
||||
}
|
||||
else {
|
||||
try {
|
||||
if(specjLazyLoad) {
|
||||
specialSpecjInitialization(false);
|
||||
}
|
||||
else
|
||||
throwLazyInitializationExceptionIfNotConnected();
|
||||
CollectionEntry entry = session.getPersistenceContext().getCollectionEntry(this);
|
||||
CollectionPersister persister = entry.getLoadedPersister();
|
||||
|
@ -134,6 +137,11 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
return true;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if(specjLazyLoad)
|
||||
session = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
read();
|
||||
return false;
|
||||
|
@ -141,6 +149,11 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
|
||||
protected Boolean readIndexExistence(Object index) {
|
||||
if (!initialized) {
|
||||
try {
|
||||
if(specjLazyLoad) {
|
||||
specialSpecjInitialization(false);
|
||||
}
|
||||
else
|
||||
throwLazyInitializationExceptionIfNotConnected();
|
||||
CollectionEntry entry = session.getPersistenceContext().getCollectionEntry(this);
|
||||
CollectionPersister persister = entry.getLoadedPersister();
|
||||
|
@ -151,13 +164,22 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
return persister.indexExists( entry.getLoadedKey(), index, session );
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if(specjLazyLoad)
|
||||
session = null;
|
||||
}
|
||||
}
|
||||
read();
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
protected Boolean readElementExistence(Object element) {
|
||||
if (!initialized) {
|
||||
try {
|
||||
if(specjLazyLoad) {
|
||||
specialSpecjInitialization(false);
|
||||
}
|
||||
else
|
||||
throwLazyInitializationExceptionIfNotConnected();
|
||||
CollectionEntry entry = session.getPersistenceContext().getCollectionEntry(this);
|
||||
CollectionPersister persister = entry.getLoadedPersister();
|
||||
|
@ -168,9 +190,13 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
return persister.elementExists( entry.getLoadedKey(), element, session );
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if(specjLazyLoad)
|
||||
session = null;
|
||||
}
|
||||
}
|
||||
read();
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
protected static final Object UNKNOWN = new MarkerObject("UNKNOWN");
|
||||
|
@ -376,10 +402,24 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
if (initializing) {
|
||||
throw new LazyInitializationException("illegal access to loading collection");
|
||||
}
|
||||
else if ( specjLazyLoad ) {
|
||||
specialSpecjInitialization(writing);
|
||||
}
|
||||
else if ( session==null ) {
|
||||
throw new LazyInitializationException("could not initialize proxy - no Session");
|
||||
}
|
||||
else if ( !session.isOpen() ) {
|
||||
throw new LazyInitializationException("could not initialize proxy - the owning Session was closed");
|
||||
}
|
||||
else if ( !session.isConnected() ) {
|
||||
throw new LazyInitializationException("could not initialize proxy - the owning Session is disconnected");
|
||||
}
|
||||
else {
|
||||
throwLazyInitializationExceptionIfNotConnected();
|
||||
session.initializeCollection(this, writing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void throwLazyInitializationExceptionIfNotConnected() {
|
||||
if ( !isConnectedToSession() ) {
|
||||
|
@ -390,6 +430,40 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
}
|
||||
}
|
||||
|
||||
protected void specialSpecjInitialization(boolean writing) {
|
||||
if ( session == null ) {
|
||||
//we have a detached collection thats set to null, reattach
|
||||
if ( sessionFactoryUuid == null ) {
|
||||
throwLazyInitializationExceptionIfNotConnected();
|
||||
}
|
||||
try {
|
||||
SessionFactoryImplementor sf = (SessionFactoryImplementor)
|
||||
SessionFactoryRegistry.INSTANCE.getSessionFactory( sessionFactoryUuid );
|
||||
session = (SessionImplementor) sf.openSession();
|
||||
CollectionPersister collectionPersister =
|
||||
session.getFactory().getCollectionPersister( this.getRole() );
|
||||
session.getPersistenceContext()
|
||||
.addUninitializedDetachedCollection( collectionPersister, this );
|
||||
|
||||
session.initializeCollection(this, writing);
|
||||
|
||||
//CollectionEntry entry = session.getPersistenceContext().getCollectionEntry(this);
|
||||
//CollectionPersister persister = entry.getLoadedPersister();
|
||||
//cachedSize = persister.getSize( entry.getLoadedKey(), session);
|
||||
|
||||
//session = null;
|
||||
}
|
||||
catch( Exception e ) {
|
||||
e.printStackTrace();
|
||||
throw new LazyInitializationException(e.getMessage());
|
||||
}
|
||||
}
|
||||
else {
|
||||
session.initializeCollection(this, writing);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void throwLazyInitializationException(String message) {
|
||||
throw new LazyInitializationException(
|
||||
"failed to lazily initialize a collection" +
|
||||
|
@ -420,6 +494,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
* @return true if this was currently associated with the given session
|
||||
*/
|
||||
public final boolean unsetSession(SessionImplementor currentSession) {
|
||||
prepareForPossibleSpecialSpecjInitialization();
|
||||
if (currentSession==this.session) {
|
||||
this.session=null;
|
||||
return true;
|
||||
|
@ -429,6 +504,22 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
}
|
||||
}
|
||||
|
||||
protected void prepareForPossibleSpecialSpecjInitialization() {
|
||||
if ( session != null ) {
|
||||
specjLazyLoad = Boolean.parseBoolean( session.getFactory().getProperties().getProperty( AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS));
|
||||
|
||||
if ( specjLazyLoad && sessionFactoryUuid == null) {
|
||||
try {
|
||||
sessionFactoryUuid = (String) session.getFactory().getReference().get("uuid").getContent();
|
||||
}
|
||||
catch (NamingException e) {
|
||||
//not much we can do if this fails...
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Associate the collection with the given session.
|
||||
* @return false if the collection was already associated with the session
|
||||
|
|
|
@ -23,14 +23,18 @@
|
|||
*/
|
||||
package org.hibernate.proxy;
|
||||
|
||||
import javax.naming.NamingException;
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.LazyInitializationException;
|
||||
import org.hibernate.SessionException;
|
||||
import org.hibernate.TransientObjectException;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.engine.spi.EntityKey;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.internal.SessionFactoryRegistry;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
||||
/**
|
||||
|
@ -50,6 +54,8 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
|
|||
private transient SessionImplementor session;
|
||||
private Boolean readOnlyBeforeAttachedToSession;
|
||||
|
||||
private String sessionFactoryUuid;
|
||||
private boolean specjLazyLoad = false;
|
||||
/**
|
||||
* For serialization from the non-pojo initializers (HHH-3309)
|
||||
*/
|
||||
|
@ -137,6 +143,7 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
|
|||
|
||||
@Override
|
||||
public final void unsetSession() {
|
||||
prepareForPossibleSpecialSpecjInitialization();
|
||||
session = null;
|
||||
readOnly = false;
|
||||
readOnlyBeforeAttachedToSession = null;
|
||||
|
@ -145,7 +152,10 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
|
|||
@Override
|
||||
public final void initialize() throws HibernateException {
|
||||
if (!initialized) {
|
||||
if ( session==null ) {
|
||||
if( specjLazyLoad ) {
|
||||
specialSpecjInitialization();
|
||||
}
|
||||
else if ( session==null ) {
|
||||
throw new LazyInitializationException("could not initialize proxy - no Session");
|
||||
}
|
||||
else if ( !session.isOpen() ) {
|
||||
|
@ -165,6 +175,55 @@ public abstract class AbstractLazyInitializer implements LazyInitializer {
|
|||
}
|
||||
}
|
||||
|
||||
protected void specialSpecjInitialization() {
|
||||
if ( session == null ) {
|
||||
//we have a detached collection thats set to null, reattach
|
||||
if ( sessionFactoryUuid == null ) {
|
||||
throw new LazyInitializationException("could not initialize proxy - no Session");
|
||||
}
|
||||
try {
|
||||
SessionFactoryImplementor sf = (SessionFactoryImplementor)
|
||||
SessionFactoryRegistry.INSTANCE.getSessionFactory( sessionFactoryUuid );
|
||||
session = (SessionImplementor) sf.openSession();
|
||||
|
||||
target = session.immediateLoad( entityName, id );
|
||||
initialized = true;
|
||||
checkTargetState();
|
||||
}
|
||||
catch( Exception e ) {
|
||||
e.printStackTrace();
|
||||
throw new LazyInitializationException(e.getMessage());
|
||||
}
|
||||
finally {
|
||||
session = null;
|
||||
}
|
||||
}
|
||||
else if(session.isOpen() && session.isConnected()) {
|
||||
target = session.immediateLoad( entityName, id );
|
||||
initialized = true;
|
||||
checkTargetState();
|
||||
}
|
||||
else {
|
||||
throw new LazyInitializationException("could not initialize proxy - Session was closed or disced");
|
||||
}
|
||||
}
|
||||
|
||||
protected void prepareForPossibleSpecialSpecjInitialization() {
|
||||
if ( session != null ) {
|
||||
specjLazyLoad =
|
||||
Boolean.parseBoolean( session.getFactory().getProperties().getProperty( AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS));
|
||||
|
||||
if ( specjLazyLoad && sessionFactoryUuid == null) {
|
||||
try {
|
||||
sessionFactoryUuid = (String) session.getFactory().getReference().get("uuid").getContent();
|
||||
}
|
||||
catch (NamingException e) {
|
||||
//not much we can do if this fails...
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkTargetState() {
|
||||
if ( !unwrap ) {
|
||||
if ( target == null ) {
|
||||
|
|
|
@ -0,0 +1,245 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2010, Red Hat, Inc. and/or its affiliates or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat, Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.test.annotations.derivedidentities.e1.b.specjmapid.ondemand;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import javax.persistence.Basic;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
import javax.persistence.Version;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@NamedQueries({
|
||||
@NamedQuery(name = CustomerDemand.QUERY_ALL,
|
||||
query = "select a from CustomerDemand a"),
|
||||
@NamedQuery(name = CustomerDemand.QUERY_COUNT,
|
||||
query = "select COUNT(a) from CustomerDemand a"),
|
||||
@NamedQuery(name = CustomerDemand.QUERY_BY_CREDIT,
|
||||
query = "SELECT c.id FROM CustomerDemand c WHERE c.creditLimit > :limit")
|
||||
})
|
||||
@Entity
|
||||
@Table(name = "O_CUSTOMERDEMAND")
|
||||
public class CustomerDemand implements Serializable {
|
||||
public static final String QUERY_ALL = "Customer.selectAll";
|
||||
public static final String QUERY_COUNT = "Customer.count";
|
||||
public static final String QUERY_BY_CREDIT = "Customer.selectByCreditLimit";
|
||||
|
||||
public static final String BAD_CREDIT = "BC";
|
||||
|
||||
@Id
|
||||
@Column(name = "C_ID")
|
||||
private int id;
|
||||
|
||||
@Column(name = "C_FIRST")
|
||||
private String firstName;
|
||||
|
||||
@Column(name = "C_LAST")
|
||||
private String lastName;
|
||||
|
||||
@Column(name = "C_CONTACT")
|
||||
private String contact;
|
||||
|
||||
@Basic(fetch = FetchType.LAZY)
|
||||
@Column(name = "C_CREDIT")
|
||||
private String credit;
|
||||
|
||||
@Column(name = "C_CREDIT_LIMIT")
|
||||
private BigDecimal creditLimit;
|
||||
|
||||
@Column(name = "C_SINCE")
|
||||
@Temporal(TemporalType.DATE)
|
||||
private Calendar since;
|
||||
|
||||
@Column(name = "C_BALANCE")
|
||||
private BigDecimal balance;
|
||||
|
||||
@Column(name = "C_YTD_PAYMENT")
|
||||
private BigDecimal ytdPayment;
|
||||
|
||||
@OneToMany(targetEntity = CustomerInventoryDemand.class,
|
||||
mappedBy = "customer",
|
||||
cascade = CascadeType.ALL,
|
||||
fetch = FetchType.LAZY)
|
||||
private List<CustomerInventoryDemand> customerInventories;
|
||||
|
||||
@Version
|
||||
@Column(name = "C_VERSION")
|
||||
private int version;
|
||||
|
||||
protected CustomerDemand() {
|
||||
}
|
||||
|
||||
public CustomerDemand(String first, String last,
|
||||
String contact, String credit, BigDecimal creditLimit,
|
||||
BigDecimal balance, BigDecimal YtdPayment) {
|
||||
|
||||
this.firstName = first;
|
||||
this.lastName = last;
|
||||
this.contact = contact;
|
||||
this.since = Calendar.getInstance();
|
||||
this.credit = credit;
|
||||
this.creditLimit = creditLimit;
|
||||
this.balance = balance;
|
||||
this.ytdPayment = YtdPayment;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer customerId) {
|
||||
this.id = customerId;
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
public void setFirstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
public String getContact() {
|
||||
return contact;
|
||||
}
|
||||
|
||||
public void setContact(String contact) {
|
||||
this.contact = contact;
|
||||
}
|
||||
|
||||
public String getCredit() {
|
||||
return credit;
|
||||
}
|
||||
|
||||
public void setCredit(String credit) {
|
||||
this.credit = credit;
|
||||
}
|
||||
|
||||
public BigDecimal getCreditLimit() {
|
||||
return creditLimit;
|
||||
}
|
||||
|
||||
public void setCreditLimit(BigDecimal creditLimit) {
|
||||
this.creditLimit = creditLimit;
|
||||
}
|
||||
|
||||
public Calendar getSince() {
|
||||
return since;
|
||||
}
|
||||
|
||||
public void setSince(Calendar since) {
|
||||
this.since = since;
|
||||
}
|
||||
|
||||
public BigDecimal getBalance() {
|
||||
return balance;
|
||||
}
|
||||
|
||||
public void setBalance(BigDecimal balance) {
|
||||
this.balance = balance;
|
||||
}
|
||||
|
||||
public void changeBalance(BigDecimal change) {
|
||||
setBalance( balance.add( change ).setScale( 2, BigDecimal.ROUND_DOWN ) );
|
||||
}
|
||||
|
||||
public BigDecimal getYtdPayment() {
|
||||
return ytdPayment;
|
||||
}
|
||||
|
||||
public void setYtdPayment(BigDecimal ytdPayment) {
|
||||
this.ytdPayment = ytdPayment;
|
||||
}
|
||||
|
||||
public List<CustomerInventoryDemand> getInventories() {
|
||||
if ( customerInventories == null ) {
|
||||
customerInventories = new ArrayList<CustomerInventoryDemand>();
|
||||
}
|
||||
return customerInventories;
|
||||
}
|
||||
|
||||
public CustomerInventoryDemand addInventory(ItemDemand item, int quantity,
|
||||
BigDecimal totalValue) {
|
||||
|
||||
CustomerInventoryDemand inventory = new CustomerInventoryDemand(
|
||||
this, item,
|
||||
quantity, totalValue
|
||||
);
|
||||
getInventories().add( inventory );
|
||||
return inventory;
|
||||
}
|
||||
|
||||
public int getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public boolean hasSufficientCredit(BigDecimal amount) {
|
||||
return !BAD_CREDIT.equals( getCredit() )
|
||||
&& creditLimit != null
|
||||
&& creditLimit.compareTo( amount ) >= 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
return id == ( ( CustomerDemand ) o ).id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new Integer( id ).hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getFirstName() + " " + this.getLastName();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2010, Red Hat, Inc. and/or its affiliates or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat, Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.test.annotations.derivedidentities.e1.b.specjmapid.ondemand;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Comparator;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.TableGenerator;
|
||||
import javax.persistence.Version;
|
||||
|
||||
@NamedQueries({
|
||||
@NamedQuery(name = "CustomerInventoryDemand.selectAll",
|
||||
query = "select a from CustomerInventoryDemand a")
|
||||
})
|
||||
@SuppressWarnings("serial")
|
||||
@Entity
|
||||
@Table(name = "O_CUSTINVENTORY")
|
||||
@IdClass(CustomerInventoryDemandPK.class)
|
||||
public class CustomerInventoryDemand implements Serializable, Comparator<CustomerInventoryDemand> {
|
||||
|
||||
@Id
|
||||
@TableGenerator(name = "inventory",
|
||||
table = "U_SEQUENCES",
|
||||
pkColumnName = "S_ID",
|
||||
valueColumnName = "S_NEXTNUM",
|
||||
pkColumnValue = "inventory",
|
||||
allocationSize = 1000)
|
||||
@GeneratedValue(strategy = GenerationType.TABLE, generator = "inventory")
|
||||
@Column(name = "CI_ID")
|
||||
private Integer id;
|
||||
|
||||
@Id
|
||||
@Column(name = "CI_CUSTOMERID", insertable = false, updatable = false)
|
||||
private int custId;
|
||||
|
||||
@ManyToOne(cascade = CascadeType.MERGE)
|
||||
@JoinColumn(name = "CI_CUSTOMERID", nullable = false)
|
||||
private CustomerDemand customer;
|
||||
|
||||
@ManyToOne(cascade = CascadeType.MERGE)
|
||||
@JoinColumn(name = "CI_ITEMID")
|
||||
private ItemDemand vehicle;
|
||||
|
||||
@Column(name = "CI_VALUE")
|
||||
private BigDecimal totalCost;
|
||||
|
||||
@Column(name = "CI_QUANTITY")
|
||||
private int quantity;
|
||||
|
||||
@Version
|
||||
@Column(name = "CI_VERSION")
|
||||
private int version;
|
||||
|
||||
protected CustomerInventoryDemand() {
|
||||
}
|
||||
|
||||
CustomerInventoryDemand(CustomerDemand customer, ItemDemand vehicle, int quantity, BigDecimal totalValue) {
|
||||
this.customer = customer;
|
||||
this.vehicle = vehicle;
|
||||
this.quantity = quantity;
|
||||
this.totalCost = totalValue;
|
||||
}
|
||||
|
||||
public ItemDemand getVehicle() {
|
||||
return vehicle;
|
||||
}
|
||||
|
||||
public BigDecimal getTotalCost() {
|
||||
return totalCost;
|
||||
}
|
||||
|
||||
public int getQuantity() {
|
||||
return quantity;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public CustomerDemand getCustomer() {
|
||||
return customer;
|
||||
}
|
||||
|
||||
public int getCustId() {
|
||||
return custId;
|
||||
}
|
||||
|
||||
public int getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public int compare(CustomerInventoryDemand cdb1, CustomerInventoryDemand cdb2) {
|
||||
return cdb1.id.compareTo( cdb2.id );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if ( obj == this ) {
|
||||
return true;
|
||||
}
|
||||
if ( obj == null || !( obj instanceof CustomerInventoryDemand ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( this.id == ( ( CustomerInventoryDemand ) obj ).id ) {
|
||||
return true;
|
||||
}
|
||||
if ( this.id != null && ( ( CustomerInventoryDemand ) obj ).id == null ) {
|
||||
return false;
|
||||
}
|
||||
if ( this.id == null && ( ( CustomerInventoryDemand ) obj ).id != null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.id.equals( ( ( CustomerInventoryDemand ) obj ).id );
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2010, Red Hat, Inc. and/or its affiliates or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat, Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.test.annotations.derivedidentities.e1.b.specjmapid.ondemand;
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
public class CustomerInventoryDemandPK implements Serializable {
|
||||
|
||||
private Integer id;
|
||||
private int custId;
|
||||
|
||||
public CustomerInventoryDemandPK() {
|
||||
}
|
||||
|
||||
public CustomerInventoryDemandPK(Integer id, int custId) {
|
||||
this.id = id;
|
||||
this.custId = custId;
|
||||
}
|
||||
|
||||
public boolean equals(Object other) {
|
||||
if ( other == this ) {
|
||||
return true;
|
||||
}
|
||||
if ( other == null || getClass() != other.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
CustomerInventoryDemandPK cip = ( CustomerInventoryDemandPK ) other;
|
||||
return ( custId == cip.custId && ( id == cip.id ||
|
||||
( id != null && id.equals( cip.id ) ) ) );
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return ( id == null ? 0 : id.hashCode() ) ^ custId;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public int getCustId() {
|
||||
return custId;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2010, Red Hat, Inc. and/or its affiliates or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat, Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.test.annotations.derivedidentities.e1.b.specjmapid.ondemand;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Version;
|
||||
|
||||
|
||||
@NamedQueries({
|
||||
@NamedQuery(name = "Item.findByCategory",
|
||||
query = "SELECT i FROM ItemDemand i WHERE i.category=:category ORDER BY i.id")
|
||||
})
|
||||
@SuppressWarnings("serial")
|
||||
@Entity
|
||||
@Table(name = "O_ITEM")
|
||||
public class ItemDemand implements Serializable {
|
||||
|
||||
public static final String QUERY_BY_CATEGORY = "Item.findByCategory";
|
||||
|
||||
@Id
|
||||
@Column(name = "I_ID")
|
||||
private String id;
|
||||
|
||||
@Column(name = "I_NAME")
|
||||
private String name;
|
||||
|
||||
@Column(name = "I_PRICE")
|
||||
private BigDecimal price;
|
||||
|
||||
@Column(name = "I_DESC")
|
||||
private String description;
|
||||
|
||||
@Column(name = "I_DISCOUNT")
|
||||
private BigDecimal discount;
|
||||
|
||||
@Column(name = "I_CATEGORY")
|
||||
private int category;
|
||||
|
||||
@Version
|
||||
@Column(name = "I_VERSION")
|
||||
int version;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String i) {
|
||||
id = i;
|
||||
}
|
||||
|
||||
public int getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
public void setCategory(int category) {
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public BigDecimal getDiscount() {
|
||||
return discount;
|
||||
}
|
||||
|
||||
public void setDiscount(BigDecimal discount) {
|
||||
if ( discount.doubleValue() < 0 || discount.doubleValue() > 100.0 ) {
|
||||
throw new IllegalArgumentException(
|
||||
this + " discount " + discount
|
||||
+ " is invalid. Must be between 0.0 and 100.0"
|
||||
);
|
||||
}
|
||||
this.discount = discount;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public BigDecimal getPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
public void setPrice(BigDecimal price) {
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
public int getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if ( other == null || other.getClass() != this.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
if ( other == this ) {
|
||||
return true;
|
||||
}
|
||||
return id.equals( ( ( ItemDemand ) other ).id );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return id.hashCode();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source
|
||||
* Copyright 2012, JBoss Inc., and individual contributors as indicated
|
||||
* by the @authors tag. See the copyright.txt in the distribution for a
|
||||
* full listing of individual contributors.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this software; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
||||
*/
|
||||
|
||||
package org.hibernate.test.annotations.derivedidentities.e1.b.specjmapid.ondemand;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.cfg.Environment;
|
||||
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
public class LazyLoadingTest extends BaseCoreFunctionalTestCase{
|
||||
|
||||
public LazyLoadingTest() {
|
||||
System.setProperty( "hibernate.enable_specj_proprietary_syntax", "true" );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnDemandLoading()
|
||||
{
|
||||
Session s;
|
||||
Transaction tx;
|
||||
s = openSession();
|
||||
tx = s.beginTransaction();
|
||||
// store entity in datastore
|
||||
CustomerDemand cust = new CustomerDemand("John", "Doe", "123456", "1.0", new BigDecimal(1),new BigDecimal(1), new BigDecimal(5));
|
||||
cust.setCredit( "GOOD" );
|
||||
s.persist(cust);
|
||||
ItemDemand item = new ItemDemand();
|
||||
item.setId("007");
|
||||
item.setName("widget");
|
||||
item.setDescription( "FooBar" );
|
||||
|
||||
|
||||
|
||||
cust.addInventory(item, 1, new BigDecimal(500));
|
||||
s.persist(item);
|
||||
s.persist(cust);
|
||||
s.flush();
|
||||
CustomerInventoryDemand eager = cust.getInventories().get( 0 );
|
||||
Integer lazyId = cust.getId();
|
||||
tx.commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
|
||||
// load the lazy entity, orm configuration loaded during @Before defines loading
|
||||
//tx = s.beginTransaction();
|
||||
CustomerDemand lazyCustomer = (CustomerDemand)s.get(CustomerDemand.class, lazyId);
|
||||
assertNotNull(lazyCustomer);
|
||||
s.clear();
|
||||
|
||||
// access the association, outside the session that loaded the entity
|
||||
List<CustomerInventoryDemand> inventories = lazyCustomer.getInventories(); // on-demand load
|
||||
assertNotNull(inventories);
|
||||
assertTrue( inventories.contains( eager ) ); // test readElementExistence
|
||||
assertEquals(1, inventories.size()); // test readSize
|
||||
//assertTrue(inventories.contains(item));
|
||||
assertEquals( cust.getCredit(), lazyCustomer.getCredit() );
|
||||
CustomerInventoryDemand inv = inventories.get(0);
|
||||
assertNotNull(inv);
|
||||
assertEquals(inv.getQuantity(), 1); // field access
|
||||
assertEquals(inv.getVehicle().getDescription(), "FooBar"); // field access
|
||||
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(Configuration cfg) {
|
||||
super.configure( cfg );
|
||||
cfg.setProperty( Environment.ENABLE_LAZY_LOAD_NO_TRANS, "true");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class[] getAnnotatedClasses() {
|
||||
return new Class[] {
|
||||
CustomerDemand.class,
|
||||
CustomerInventoryDemand.class,
|
||||
CustomerInventoryDemandPK.class,
|
||||
ItemDemand.class
|
||||
|
||||
};
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue