HHH-17532 Fix NPE when load-collection is used for collection within embeddable
This commit is contained in:
parent
c74ab4bc66
commit
f4df70a956
|
@ -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(
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
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<Player> players = t2.getDetails().getPlayers();
|
||||
Iterator<Player> 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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
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<Player> players = new HashSet<Player>();
|
||||
|
||||
@OneToMany(targetEntity = Player.class, mappedBy = "team", fetch = FetchType.EAGER)
|
||||
@Fetch(FetchMode.SELECT)
|
||||
@Loader(namedQuery = "loadByTeam")
|
||||
public Set<Player> getPlayers() {
|
||||
return players;
|
||||
}
|
||||
|
||||
public void setPlayers(Set<Player> players) {
|
||||
this.players = players;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
~ 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
-->
|
||||
<!DOCTYPE hibernate-mapping PUBLIC
|
||||
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||
|
||||
<!--
|
||||
|
||||
Used to demonstrate the declarative configuration
|
||||
of both hbm files and annotated classes
|
||||
See hibernate.cfg.xml and ConfigurationTest
|
||||
|
||||
-->
|
||||
|
||||
<hibernate-mapping package="org.hibernate.test.annotations.loader.collectioninembedded">
|
||||
|
||||
<sql-query name="loadByTeam">
|
||||
<load-collection alias="p" role="org.hibernate.test.annotations.loader.collectioninembedded.Team.details.players"/>
|
||||
select {p.*} from Player p where p.team_id = ?1
|
||||
</sql-query>
|
||||
|
||||
</hibernate-mapping>
|
Loading…
Reference in New Issue