diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ResultSetMappingBinder.java b/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ResultSetMappingBinder.java index eb88399059..b33e1438a4 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ResultSetMappingBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/hbm/ResultSetMappingBinder.java @@ -214,20 +214,23 @@ public abstract class ResultSetMappingBinder { JaxbHbmNativeQueryCollectionLoadReturnType rtnSource, HbmLocalMetadataBuildingContext context, int queryReturnPosition) { - final int dot = rtnSource.getRole().lastIndexOf( '.' ); - if ( dot == -1 ) { - throw new MappingException( - String.format( - Locale.ENGLISH, - "Collection attribute for sql query return [%s] not formatted correctly {OwnerClassName.propertyName}", - rtnSource.getAlias() - ), - context.getOrigin() - ); + PersistentClass entityBinding = null; + int dot = rtnSource.getRole().length(); + while ( entityBinding == null ) { + dot = rtnSource.getRole().lastIndexOf( '.', dot - 1); + if ( dot == -1 ) { + throw new MappingException( + String.format( + Locale.ENGLISH, + "Collection attribute for sql query return [%s] not formatted correctly {OwnerClassName.propertyName}", + rtnSource.getAlias() + ), + context.getOrigin() + ); + } + entityBinding = context.findEntityBinding( null, rtnSource.getRole().substring( 0, dot ) ); } - - String ownerClassName = context.findEntityBinding( null, rtnSource.getRole().substring( 0, dot ) ) - .getClassName(); + String ownerClassName = entityBinding.getClassName(); String ownerPropertyName = rtnSource.getRole().substring( dot + 1 ); return new NativeSQLQueryCollectionReturn( diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/loader/collectioninembedded/LoaderCollectionInEmbeddedTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/loader/collectioninembedded/LoaderCollectionInEmbeddedTest.java new file mode 100644 index 0000000000..6a63338bce --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/loader/collectioninembedded/LoaderCollectionInEmbeddedTest.java @@ -0,0 +1,76 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.test.annotations.loader.collectioninembedded; + +import java.util.Iterator; +import java.util.Set; + +import org.hibernate.ObjectNotFoundException; +import org.hibernate.Session; +import org.hibernate.Transaction; +import org.hibernate.resource.transaction.spi.TransactionStatus; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +@TestForIssue(jiraKey = "") +public class LoaderCollectionInEmbeddedTest extends BaseCoreFunctionalTestCase { + @Override + protected String[] getXmlFiles() { + return new String[] { + "org/hibernate/test/annotations/loader/collectioninembedded/Loader.hbm.xml" + }; + } + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[]{ + Player.class, + Team.class + }; + } + + @Test + public void testBasic() throws Exception { + // set up data... + Session s = openSession( ); + Transaction tx = s.beginTransaction(); + Team t = new Team(); + Player p = new Player(); + p.setName( "me" ); + t.getDetails().getPlayers().add( p ); + p.setTeam( t ); + s.persist(p); + s.persist( t ); + tx.commit(); + s.close(); + + s = openSession(); + tx = s.beginTransaction(); + Team t2 = s.load( Team.class, t.getId() ); + Set players = t2.getDetails().getPlayers(); + Iterator iterator = players.iterator(); + assertEquals( "me", iterator.next().getName() ); + tx.commit(); + s.close(); + + // clean up data + s = openSession(); + tx = s.beginTransaction(); + t = s.get( Team.class, t2.getId() ); + p = s.get( Player.class, p.getId() ); + s.delete( p ); + s.delete( t ); + tx.commit(); + s.close(); + } +} + diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/loader/collectioninembedded/Player.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/loader/collectioninembedded/Player.java new file mode 100644 index 0000000000..bd51a04cd7 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/loader/collectioninembedded/Player.java @@ -0,0 +1,53 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.test.annotations.loader.collectioninembedded; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; + +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; + +@Entity +public class Player { + + private Long id; + private Team team; + private String name; + + @Id + @GeneratedValue + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + @ManyToOne(targetEntity = Team.class) + @Fetch(FetchMode.SELECT) + @JoinColumn(name = "team_id") + public Team getTeam() { + return team; + } + + public void setTeam(Team team) { + this.team = team; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/loader/collectioninembedded/Team.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/loader/collectioninembedded/Team.java new file mode 100644 index 0000000000..96438b1f63 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/loader/collectioninembedded/Team.java @@ -0,0 +1,42 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.test.annotations.loader.collectioninembedded; +import java.util.HashSet; +import java.util.Set; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.OneToMany; + +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; +import org.hibernate.annotations.Loader; + +@Entity +public class Team { + private Long id; + private TeamDetails details = new TeamDetails(); + + @Id + @GeneratedValue + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public TeamDetails getDetails() { + return details; + } + + public void setDetails(TeamDetails details) { + this.details = details; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/loader/collectioninembedded/TeamDetails.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/loader/collectioninembedded/TeamDetails.java new file mode 100644 index 0000000000..c4e8763fba --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/loader/collectioninembedded/TeamDetails.java @@ -0,0 +1,35 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.test.annotations.loader.collectioninembedded; + +import java.util.HashSet; +import java.util.Set; +import javax.persistence.Embeddable; +import javax.persistence.FetchType; +import javax.persistence.OneToMany; + +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; +import org.hibernate.annotations.Loader; + +@Embeddable +public class TeamDetails { + + private Set players = new HashSet(); + + @OneToMany(targetEntity = Player.class, mappedBy = "team", fetch = FetchType.EAGER) + @Fetch(FetchMode.SELECT) + @Loader(namedQuery = "loadByTeam") + public Set getPlayers() { + return players; + } + + public void setPlayers(Set players) { + this.players = players; + } + +} diff --git a/hibernate-core/src/test/resources/org/hibernate/test/annotations/loader/collectioninembedded/Loader.hbm.xml b/hibernate-core/src/test/resources/org/hibernate/test/annotations/loader/collectioninembedded/Loader.hbm.xml new file mode 100644 index 0000000000..a04a27858f --- /dev/null +++ b/hibernate-core/src/test/resources/org/hibernate/test/annotations/loader/collectioninembedded/Loader.hbm.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + select {p.*} from Player p where p.team_id = ?1 + + + \ No newline at end of file