HHH-12150 - @MapKeyColumn referring to otherwise non-mapped column
This commit is contained in:
parent
9af5655100
commit
8c2a683356
|
@ -15,6 +15,7 @@ import javax.persistence.AttributeOverrides;
|
||||||
import javax.persistence.ConstraintMode;
|
import javax.persistence.ConstraintMode;
|
||||||
import javax.persistence.InheritanceType;
|
import javax.persistence.InheritanceType;
|
||||||
import javax.persistence.MapKeyClass;
|
import javax.persistence.MapKeyClass;
|
||||||
|
import javax.persistence.MapKeyColumn;
|
||||||
import javax.persistence.MapKeyJoinColumn;
|
import javax.persistence.MapKeyJoinColumn;
|
||||||
import javax.persistence.MapKeyJoinColumns;
|
import javax.persistence.MapKeyJoinColumns;
|
||||||
|
|
||||||
|
@ -102,10 +103,55 @@ public class MapBinder extends CollectionBinder {
|
||||||
mapKeyColumns, mapKeyManyToManyColumns,
|
mapKeyColumns, mapKeyManyToManyColumns,
|
||||||
inverseColumns != null ? inverseColumns[0].getPropertyName() : null
|
inverseColumns != null ? inverseColumns[0].getPropertyName() : null
|
||||||
);
|
);
|
||||||
|
makeOneToManyMapKeyColumnNullableIfNotInProperty( property );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void makeOneToManyMapKeyColumnNullableIfNotInProperty(
|
||||||
|
final XProperty property) {
|
||||||
|
final org.hibernate.mapping.Map map = (org.hibernate.mapping.Map) this.collection;
|
||||||
|
if ( map.isOneToMany() &&
|
||||||
|
property.isAnnotationPresent( MapKeyColumn.class ) ) {
|
||||||
|
final Value indexValue = map.getIndex();
|
||||||
|
if ( indexValue.getColumnSpan() != 1 ) {
|
||||||
|
throw new AssertionFailure( "Map key mapped by @MapKeyColumn does not have 1 column" );
|
||||||
|
}
|
||||||
|
final Selectable selectable = indexValue.getColumnIterator().next();
|
||||||
|
if ( selectable.isFormula() ) {
|
||||||
|
throw new AssertionFailure( "Map key mapped by @MapKeyColumn is a Formula" );
|
||||||
|
}
|
||||||
|
Column column = (Column) map.getIndex().getColumnIterator().next();
|
||||||
|
if ( !column.isNullable() ) {
|
||||||
|
final PersistentClass persistentClass = ( ( OneToMany ) map.getElement() ).getAssociatedClass();
|
||||||
|
// check if the index column has been mapped by the associated entity to a property;
|
||||||
|
// @MapKeyColumn only maps a column to the primary table for the one-to-many, so we only
|
||||||
|
// need to check "un-joined" properties.
|
||||||
|
if ( !propertyIteratorContainsColumn( persistentClass.getUnjoinedPropertyIterator(), column ) ) {
|
||||||
|
// The index column is not mapped to an associated entity property so we can
|
||||||
|
// safely make the index column nullable.
|
||||||
|
column.setNullable( true );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean propertyIteratorContainsColumn(Iterator propertyIterator, Column column) {
|
||||||
|
for ( Iterator it = propertyIterator; it.hasNext(); ) {
|
||||||
|
final Property property = (Property) it.next();
|
||||||
|
for ( Iterator<Selectable> selectableIterator = property.getColumnIterator(); selectableIterator.hasNext(); ) {
|
||||||
|
final Selectable selectable = selectableIterator.next();
|
||||||
|
if ( column.equals( selectable ) ) {
|
||||||
|
final Column iteratedColumn = (Column) selectable;
|
||||||
|
if ( column.getValue().getTable().equals( iteratedColumn.getValue().getTable() ) ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private void bindKeyFromAssociationTable(
|
private void bindKeyFromAssociationTable(
|
||||||
XClass collType,
|
XClass collType,
|
||||||
Map persistentClasses,
|
Map persistentClasses,
|
||||||
|
|
|
@ -0,0 +1,170 @@
|
||||||
|
/*
|
||||||
|
* 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.jpa.compliance.tck2_2.mapkeycolumn;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.ElementCollection;
|
||||||
|
import javax.persistence.Embeddable;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.MapKeyColumn;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import org.hibernate.boot.MetadataSources;
|
||||||
|
|
||||||
|
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class MapKeyColumnElementCollectionTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReferenceToAlreadyMappedColumn() {
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
AddressCapable2 holder = new AddressCapable2( 1, "osd");
|
||||||
|
|
||||||
|
session.persist( holder );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
AddressCapable2 holder = session.get( AddressCapable2.class, 1 );
|
||||||
|
Address2 address = new Address2( 1, "123 Main St" );
|
||||||
|
address.type = "work";
|
||||||
|
|
||||||
|
holder.addresses.put( "work", address );
|
||||||
|
|
||||||
|
session.persist( holder );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
AddressCapable2 holder = session.get( AddressCapable2.class, 1 );
|
||||||
|
assertEquals( 1, holder.addresses.size() );
|
||||||
|
final Map.Entry<String,Address2> entry = holder.addresses.entrySet().iterator().next();
|
||||||
|
assertEquals( "work", entry.getKey() );
|
||||||
|
assertEquals( "work", entry.getValue().type );
|
||||||
|
session.remove( holder );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReferenceToNonMappedColumn() {
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
AddressCapable holder = new AddressCapable( 1, "osd");
|
||||||
|
|
||||||
|
session.persist( holder );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
AddressCapable holder = session.get( AddressCapable.class, 1 );
|
||||||
|
|
||||||
|
holder.addresses.put( "work", new Address( 1, "123 Main St" ) );
|
||||||
|
|
||||||
|
session.persist( holder );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
AddressCapable holder = session.get( AddressCapable.class, 1 );
|
||||||
|
assertEquals( 1, holder.addresses.size() );
|
||||||
|
final Map.Entry<String,Address> entry = holder.addresses.entrySet().iterator().next();
|
||||||
|
assertEquals( "work", entry.getKey() );
|
||||||
|
session.remove( holder );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void applyMetadataSources(MetadataSources sources) {
|
||||||
|
super.applyMetadataSources( sources );
|
||||||
|
|
||||||
|
sources.addAnnotatedClass( AddressCapable.class );
|
||||||
|
sources.addAnnotatedClass( AddressCapable2.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity( name = "AddressCapable" )
|
||||||
|
@Table( name = "address_capables" )
|
||||||
|
public static class AddressCapable {
|
||||||
|
@Id
|
||||||
|
public Integer id;
|
||||||
|
public String name;
|
||||||
|
@MapKeyColumn( name = "a_type" )
|
||||||
|
@ElementCollection
|
||||||
|
public Map<String,Address> addresses = new HashMap<>();
|
||||||
|
|
||||||
|
public AddressCapable() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public AddressCapable(Integer id, String name) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Embeddable
|
||||||
|
public static class Address {
|
||||||
|
public Integer buildingNumber;
|
||||||
|
public String street;
|
||||||
|
|
||||||
|
public Address() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address(Integer buildingNumber, String street) {
|
||||||
|
this.buildingNumber = buildingNumber;
|
||||||
|
this.street = street;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity( name = "AddressCapable2" )
|
||||||
|
@Table( name = "address_capables2" )
|
||||||
|
public static class AddressCapable2 {
|
||||||
|
@Id
|
||||||
|
public Integer id;
|
||||||
|
public String name;
|
||||||
|
@MapKeyColumn( name = "a_type", insertable = false, updatable = false)
|
||||||
|
@ElementCollection
|
||||||
|
public Map<String,Address2> addresses = new HashMap<>();
|
||||||
|
|
||||||
|
public AddressCapable2() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public AddressCapable2(Integer id, String name) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Embeddable
|
||||||
|
public static class Address2 {
|
||||||
|
public Integer buildingNumber;
|
||||||
|
public String street;
|
||||||
|
@Column( name = "a_type" )
|
||||||
|
public String type;
|
||||||
|
|
||||||
|
public Address2() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address2(Integer buildingNumber, String street) {
|
||||||
|
this.buildingNumber = buildingNumber;
|
||||||
|
this.street = street;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,179 @@
|
||||||
|
/*
|
||||||
|
* 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.jpa.compliance.tck2_2.mapkeycolumn;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.ManyToMany;
|
||||||
|
import javax.persistence.MapKeyColumn;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import org.hibernate.boot.MetadataSources;
|
||||||
|
|
||||||
|
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class MapKeyColumnManyToManyTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReferenceToAlreadyMappedColumn() {
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
AddressCapable2 holder = new AddressCapable2( 1, "osd");
|
||||||
|
Address2 address = new Address2( 1, "123 Main St" );
|
||||||
|
|
||||||
|
session.persist( holder );
|
||||||
|
session.persist( address );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
AddressCapable2 holder = session.get( AddressCapable2.class, 1 );
|
||||||
|
Address2 address = session.get( Address2.class, 1 );
|
||||||
|
|
||||||
|
holder.addresses.put( "work", address );
|
||||||
|
|
||||||
|
session.persist( holder );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
AddressCapable2 holder = session.get( AddressCapable2.class, 1 );
|
||||||
|
assertEquals( 1, holder.addresses.size() );
|
||||||
|
final Map.Entry<String,Address2> entry = holder.addresses.entrySet().iterator().next();
|
||||||
|
assertEquals( "work", entry.getKey() );
|
||||||
|
assertEquals( null, entry.getValue().type );
|
||||||
|
session.remove( holder );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReferenceToNonMappedColumn() {
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
AddressCapable holder = new AddressCapable( 1, "osd");
|
||||||
|
Address address = new Address( 1, "123 Main St" );
|
||||||
|
|
||||||
|
session.persist( holder );
|
||||||
|
session.persist( address );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
AddressCapable holder = session.get( AddressCapable.class, 1 );
|
||||||
|
Address address = session.get( Address.class, 1 );
|
||||||
|
|
||||||
|
holder.addresses.put( "work", address );
|
||||||
|
|
||||||
|
session.persist( holder );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
AddressCapable holder = session.get( AddressCapable.class, 1 );
|
||||||
|
assertEquals( 1, holder.addresses.size() );
|
||||||
|
final Map.Entry<String,Address> entry = holder.addresses.entrySet().iterator().next();
|
||||||
|
assertEquals( "work", entry.getKey() );
|
||||||
|
session.remove( holder );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void applyMetadataSources(MetadataSources sources) {
|
||||||
|
super.applyMetadataSources( sources );
|
||||||
|
|
||||||
|
sources.addAnnotatedClass( AddressCapable.class );
|
||||||
|
sources.addAnnotatedClass( AddressCapable2.class );
|
||||||
|
sources.addAnnotatedClass( Address.class );
|
||||||
|
sources.addAnnotatedClass( Address2.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity( name = "AddressCapable" )
|
||||||
|
@Table( name = "address_capables" )
|
||||||
|
public static class AddressCapable {
|
||||||
|
@Id
|
||||||
|
public Integer id;
|
||||||
|
public String name;
|
||||||
|
@MapKeyColumn( name = "a_type" )
|
||||||
|
@ManyToMany( cascade = {CascadeType.PERSIST, CascadeType.REMOVE} )
|
||||||
|
public Map<String,Address> addresses = new HashMap<>();
|
||||||
|
|
||||||
|
public AddressCapable() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public AddressCapable(Integer id, String name) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity( name = "Address" )
|
||||||
|
@Table( name = "addresses" )
|
||||||
|
public static class Address {
|
||||||
|
@Id
|
||||||
|
public Integer id;
|
||||||
|
public String street;
|
||||||
|
|
||||||
|
public Address() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address(Integer id, String street) {
|
||||||
|
this.id = id;
|
||||||
|
this.street = street;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity( name = "AddressCapable2" )
|
||||||
|
@Table( name = "address_capables2" )
|
||||||
|
public static class AddressCapable2 {
|
||||||
|
@Id
|
||||||
|
public Integer id;
|
||||||
|
public String name;
|
||||||
|
@MapKeyColumn( name = "a_type" )
|
||||||
|
@ManyToMany( cascade = {CascadeType.PERSIST, CascadeType.REMOVE} )
|
||||||
|
public Map<String,Address2> addresses = new HashMap<>();
|
||||||
|
|
||||||
|
public AddressCapable2() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public AddressCapable2(Integer id, String name) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity( name = "Address2" )
|
||||||
|
@Table( name = "addresses2" )
|
||||||
|
public static class Address2 {
|
||||||
|
@Id
|
||||||
|
public Integer id;
|
||||||
|
public String street;
|
||||||
|
@Column( name = "a_type" )
|
||||||
|
public String type;
|
||||||
|
|
||||||
|
public Address2() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address2(Integer id, String street) {
|
||||||
|
this.id = id;
|
||||||
|
this.street = street;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
* 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
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.jpa.compliance.tck2_2;
|
package org.hibernate.test.jpa.compliance.tck2_2.mapkeycolumn;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -22,26 +22,42 @@ import org.hibernate.boot.MetadataSources;
|
||||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class MapKeyColumnTest extends BaseNonConfigCoreFunctionalTestCase {
|
public class MapKeyColumnOneToManyFKTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReferenceToAlreadyMappedColumn() {
|
public void testReferenceToAlreadyMappedColumn() {
|
||||||
inTransaction(
|
inTransaction(
|
||||||
session -> {
|
session -> {
|
||||||
AddressCapable2 holder = new AddressCapable2( 1, "osd");
|
AddressCapable2 holder = new AddressCapable2( 1, "osd");
|
||||||
holder.addresses.put( "work", new Address2( 1, "123 Main St" ) );
|
Address2 address = new Address2( 1, "123 Main St" );
|
||||||
|
|
||||||
|
session.persist( holder );
|
||||||
|
session.persist( address );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
AddressCapable2 holder = session.get( AddressCapable2.class, 1 );
|
||||||
|
Address2 address = session.get( Address2.class, 1 );
|
||||||
|
|
||||||
|
holder.addresses.put( "work", address );
|
||||||
|
|
||||||
session.persist( holder );
|
session.persist( holder );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
inTransaction(
|
inTransaction(
|
||||||
session -> {
|
session -> {
|
||||||
session.remove(
|
AddressCapable2 holder = session.get( AddressCapable2.class, 1 );
|
||||||
session.byId( AddressCapable2.class ).load( 1 )
|
assertEquals( 1, holder.addresses.size() );
|
||||||
);
|
final Map.Entry<String,Address2> entry = holder.addresses.entrySet().iterator().next();
|
||||||
|
assertEquals( "work", entry.getKey() );
|
||||||
|
assertEquals( "work", entry.getValue().type );
|
||||||
|
session.remove( holder );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -51,16 +67,29 @@ public class MapKeyColumnTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||||
inTransaction(
|
inTransaction(
|
||||||
session -> {
|
session -> {
|
||||||
AddressCapable holder = new AddressCapable( 1, "osd");
|
AddressCapable holder = new AddressCapable( 1, "osd");
|
||||||
holder.addresses.put( "work", new Address( 1, "123 Main St" ) );
|
Address address = new Address( 1, "123 Main St" );
|
||||||
|
|
||||||
|
session.persist( holder );
|
||||||
|
session.persist( address );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
AddressCapable holder = session.get( AddressCapable.class, 1 );
|
||||||
|
Address address = session.get( Address.class, 1 );
|
||||||
|
|
||||||
|
holder.addresses.put( "work", address );
|
||||||
|
|
||||||
session.persist( holder );
|
session.persist( holder );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
inTransaction(
|
inTransaction(
|
||||||
session -> {
|
session -> {
|
||||||
session.remove(
|
AddressCapable holder = session.get( AddressCapable.class, 1 );
|
||||||
session.byId( AddressCapable.class ).load( 1 )
|
assertEquals( 1, holder.addresses.size() );
|
||||||
);
|
final Map.Entry<String,Address> entry = holder.addresses.entrySet().iterator().next();
|
||||||
|
assertEquals( "work", entry.getKey() );
|
||||||
|
session.remove( holder );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
|
@ -0,0 +1,178 @@
|
||||||
|
/*
|
||||||
|
* 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.jpa.compliance.tck2_2.mapkeycolumn;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.MapKeyColumn;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import org.hibernate.boot.MetadataSources;
|
||||||
|
|
||||||
|
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class MapKeyColumnOneToManyJoinTableTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReferenceToAlreadyMappedColumn() {
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
AddressCapable2 holder = new AddressCapable2( 1, "osd");
|
||||||
|
Address2 address = new Address2( 1, "123 Main St" );
|
||||||
|
|
||||||
|
session.persist( holder );
|
||||||
|
session.persist( address );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
AddressCapable2 holder = session.get( AddressCapable2.class, 1 );
|
||||||
|
Address2 address = session.get( Address2.class, 1 );
|
||||||
|
|
||||||
|
holder.addresses.put( "work", address );
|
||||||
|
|
||||||
|
session.persist( holder );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
AddressCapable2 holder = session.get( AddressCapable2.class, 1 );
|
||||||
|
assertEquals( 1, holder.addresses.size() );
|
||||||
|
final Map.Entry<String,Address2> entry = holder.addresses.entrySet().iterator().next();
|
||||||
|
assertEquals( "work", entry.getKey() );
|
||||||
|
assertEquals( null, entry.getValue().type );
|
||||||
|
session.remove( holder );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReferenceToNonMappedColumn() {
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
AddressCapable holder = new AddressCapable( 1, "osd");
|
||||||
|
Address address = new Address( 1, "123 Main St" );
|
||||||
|
|
||||||
|
session.persist( holder );
|
||||||
|
session.persist( address );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
AddressCapable holder = session.get( AddressCapable.class, 1 );
|
||||||
|
Address address = session.get( Address.class, 1 );
|
||||||
|
|
||||||
|
holder.addresses.put( "work", address );
|
||||||
|
|
||||||
|
session.persist( holder );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
inTransaction(
|
||||||
|
session -> {
|
||||||
|
AddressCapable holder = session.get( AddressCapable.class, 1 );
|
||||||
|
assertEquals( 1, holder.addresses.size() );
|
||||||
|
final Map.Entry<String,Address> entry = holder.addresses.entrySet().iterator().next();
|
||||||
|
assertEquals( "work", entry.getKey() );
|
||||||
|
session.remove( holder );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void applyMetadataSources(MetadataSources sources) {
|
||||||
|
super.applyMetadataSources( sources );
|
||||||
|
|
||||||
|
sources.addAnnotatedClass( AddressCapable.class );
|
||||||
|
sources.addAnnotatedClass( AddressCapable2.class );
|
||||||
|
sources.addAnnotatedClass( Address.class );
|
||||||
|
sources.addAnnotatedClass( Address2.class );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity( name = "AddressCapable" )
|
||||||
|
@Table( name = "address_capables" )
|
||||||
|
public static class AddressCapable {
|
||||||
|
@Id
|
||||||
|
public Integer id;
|
||||||
|
public String name;
|
||||||
|
@MapKeyColumn( name = "a_type" )
|
||||||
|
@OneToMany( cascade = {CascadeType.PERSIST, CascadeType.REMOVE} )
|
||||||
|
public Map<String,Address> addresses = new HashMap<>();
|
||||||
|
|
||||||
|
public AddressCapable() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public AddressCapable(Integer id, String name) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity( name = "Address" )
|
||||||
|
@Table( name = "addresses" )
|
||||||
|
public static class Address {
|
||||||
|
@Id
|
||||||
|
public Integer id;
|
||||||
|
public String street;
|
||||||
|
|
||||||
|
public Address() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address(Integer id, String street) {
|
||||||
|
this.id = id;
|
||||||
|
this.street = street;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity( name = "AddressCapable2" )
|
||||||
|
@Table( name = "address_capables2" )
|
||||||
|
public static class AddressCapable2 {
|
||||||
|
@Id
|
||||||
|
public Integer id;
|
||||||
|
public String name;
|
||||||
|
@MapKeyColumn( name = "a_type" )
|
||||||
|
@OneToMany( cascade = {CascadeType.PERSIST, CascadeType.REMOVE} )
|
||||||
|
public Map<String,Address2> addresses = new HashMap<>();
|
||||||
|
|
||||||
|
public AddressCapable2() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public AddressCapable2(Integer id, String name) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity( name = "Address2" )
|
||||||
|
@Table( name = "addresses2" )
|
||||||
|
public static class Address2 {
|
||||||
|
@Id
|
||||||
|
public Integer id;
|
||||||
|
public String street;
|
||||||
|
@Column( name = "a_type" )
|
||||||
|
public String type;
|
||||||
|
|
||||||
|
public Address2() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address2(Integer id, String street) {
|
||||||
|
this.id = id;
|
||||||
|
this.street = street;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue