From aa2451407ed90b94ed321d024d8e91a88c54a9bb Mon Sep 17 00:00:00 2001 From: Dmitry Panov Date: Tue, 29 Jan 2019 16:21:12 +0000 Subject: [PATCH] HHH-13236 Honour @Column/insertable on element collections --- .../AbstractCollectionPersister.java | 14 ++- .../NonInsertableColumnTest.java | 108 ++++++++++++++++++ 2 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 hibernate-core/src/test/java/org/hibernate/test/collection/nonInsertable/NonInsertableColumnTest.java diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java index adbff2b77f..ad25a947d2 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java @@ -160,6 +160,7 @@ public abstract class AbstractCollectionPersister protected final String[] elementColumnReaderTemplates; protected final String[] elementFormulaTemplates; protected final String[] elementFormulas; + protected final boolean[] elementColumnIsGettable; protected final boolean[] elementColumnIsSettable; protected final boolean[] elementColumnIsInPrimaryKey; protected final String[] indexColumnAliases; @@ -332,9 +333,15 @@ public abstract class AbstractCollectionPersister elementFormulaTemplates = new String[elementSpan]; elementFormulas = new String[elementSpan]; elementColumnIsSettable = new boolean[elementSpan]; + elementColumnIsGettable = new boolean[elementSpan]; elementColumnIsInPrimaryKey = new boolean[elementSpan]; boolean isPureFormula = true; boolean hasNotNullableColumns = false; + boolean oneToMany = collectionBinding.isOneToMany(); + boolean[] columnInsertability = null; + if (!oneToMany) { + columnInsertability = collectionBinding.getElement().getColumnInsertability(); + } int j = 0; iter = collectionBinding.getElement().getColumnIterator(); while ( iter.hasNext() ) { @@ -351,7 +358,8 @@ public abstract class AbstractCollectionPersister elementColumnWriters[j] = col.getWriteExpr(); elementColumnReaders[j] = col.getReadExpr( dialect ); elementColumnReaderTemplates[j] = col.getTemplate( dialect, factory.getSqlFunctionRegistry() ); - elementColumnIsSettable[j] = true; + elementColumnIsGettable[j] = true; + elementColumnIsSettable[j] = oneToMany || columnInsertability[j]; elementColumnIsInPrimaryKey[j] = !col.isNullable(); if ( !col.isNullable() ) { hasNotNullableColumns = true; @@ -1087,8 +1095,8 @@ public abstract class AbstractCollectionPersister } protected void appendElementColumns(SelectFragment frag, String elemAlias) { - for ( int i = 0; i < elementColumnIsSettable.length; i++ ) { - if ( elementColumnIsSettable[i] ) { + for ( int i = 0; i < elementColumnIsGettable.length; i++ ) { + if ( elementColumnIsGettable[i] ) { frag.addColumnTemplate( elemAlias, elementColumnReaderTemplates[i], elementColumnAliases[i] ); } else { diff --git a/hibernate-core/src/test/java/org/hibernate/test/collection/nonInsertable/NonInsertableColumnTest.java b/hibernate-core/src/test/java/org/hibernate/test/collection/nonInsertable/NonInsertableColumnTest.java new file mode 100644 index 0000000000..ef664eaca9 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/collection/nonInsertable/NonInsertableColumnTest.java @@ -0,0 +1,108 @@ +package org.hibernate.test.collection.nonInsertable; + +import org.hibernate.HibernateException; +import org.hibernate.Session; +import org.hibernate.Transaction; + +import javax.persistence.*; + +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.Configuration; +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.*; + +@TestForIssue(jiraKey = "HHH-13236") +public class NonInsertableColumnTest extends BaseCoreFunctionalTestCase { + + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + Parent.class, + Child.class + }; + } + + @Override + protected void configure(Configuration configuration) { + super.configure( configuration ); + + configuration.setProperty( AvailableSettings.SHOW_SQL, "true" ); + } + + @Test + public void test() { + Session session = null; + Transaction transaction = null; + + try { + session = openSession(); + transaction = session.beginTransaction(); + + Child child = new Child(); + child.field = "Test"; + child.nonInsertable = "nonInsertable"; + child.nonUpdatable = "nonUpdatable"; + + Parent parent = new Parent(); + parent.children = Arrays.asList(child); + + session.persist(parent); + + session.flush(); + + transaction.commit(); + + session.clear(); + + Parent loaded = session.get(Parent.class, parent.id); + assertEquals("nonUpdatable", loaded.children.get(0).nonUpdatable); + assertNull(loaded.children.get(0).nonInsertable); + assertEquals("Test", loaded.children.get(0).field); + assertEquals("Test", loaded.children.get(0).shadowField); + } catch (HibernateException e) { + if (transaction != null) { + transaction.rollback(); + } + fail(e.getMessage()); + } finally { + if (session != null) { + session.close(); + } + } + + } + + @Entity(name="Parent") + public static class Parent { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + public Long id; + + @ElementCollection + public List children; + } + + @Embeddable + public static class Child { + + @Column(name="field") + public String field; + + @Column(insertable = false) + public String nonInsertable; + + @Column(updatable = false) + public String nonUpdatable; + + @Column(name="field", insertable = false, updatable = false) + public String shadowField; + } + +}