From a450630f3648fe4c0dde0b7e82c56af09d5b5112 Mon Sep 17 00:00:00 2001 From: Brett Meyer Date: Thu, 5 Sep 2013 12:39:55 -0400 Subject: [PATCH] HHH-8464 normalize quoting on join column --- .../org/hibernate/cfg/Ejb3JoinColumn.java | 15 +++--- .../test/annotations/quote/House.java | 53 +++++++++++++++++++ .../annotations/quote/QuoteGlobalTest.java | 3 +- .../test/annotations/quote/QuoteTest.java | 36 +++++++++++-- .../test/annotations/quote/User.java | 49 +++++++++++++++-- 5 files changed, 140 insertions(+), 16 deletions(-) create mode 100644 hibernate-core/src/test/java/org/hibernate/test/annotations/quote/House.java diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/Ejb3JoinColumn.java b/hibernate-core/src/main/java/org/hibernate/cfg/Ejb3JoinColumn.java index bcc79fd21f..7adee29eef 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/Ejb3JoinColumn.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/Ejb3JoinColumn.java @@ -510,14 +510,17 @@ public void linkValueUsingAColumnCopy(Column column, SimpleValue value) { @Override protected void addColumnBinding(SimpleValue value) { if ( StringHelper.isEmpty( mappedBy ) ) { - String unquotedLogColName = StringHelper.unquote( getLogicalColumnName() ); - String unquotedRefColumn = StringHelper.unquote( getReferencedColumn() ); - String logicalColumnName = getMappings().getNamingStrategy() + final ObjectNameNormalizer nameNormalizer = getMappings().getObjectNameNormalizer(); + final String logicalColumnName = nameNormalizer.normalizeIdentifierQuoting( getLogicalColumnName() ); + final String referencedColumn = nameNormalizer.normalizeIdentifierQuoting( getReferencedColumn() ); + final String unquotedLogColName = StringHelper.unquote( logicalColumnName ); + final String unquotedRefColumn = StringHelper.unquote( referencedColumn ); + String logicalCollectionColumnName = getMappings().getNamingStrategy() .logicalCollectionColumnName( unquotedLogColName, getPropertyName(), unquotedRefColumn ); - if ( StringHelper.isQuoted( getLogicalColumnName() ) || StringHelper.isQuoted( getLogicalColumnName() ) ) { - logicalColumnName = StringHelper.quote( logicalColumnName ); + if ( StringHelper.isQuoted( logicalColumnName ) || StringHelper.isQuoted( referencedColumn ) ) { + logicalCollectionColumnName = StringHelper.quote( logicalCollectionColumnName ); } - getMappings().addColumnBinding( logicalColumnName, getMappingColumn(), value.getTable() ); + getMappings().addColumnBinding( logicalCollectionColumnName, getMappingColumn(), value.getTable() ); } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/quote/House.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/quote/House.java new file mode 100644 index 0000000000..0e8eca2aab --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/quote/House.java @@ -0,0 +1,53 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * JBoss, Home of Professional Open Source + * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors + * as indicated by the @authors tag. All rights reserved. + * See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * 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, v. 2.1. + * This program is distributed in the hope that it will be useful, but WITHOUT A + * 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, + * v.2.1 along with this distribution; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +package org.hibernate.test.annotations.quote; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +/** + * @author Brett Meyer + */ +@Entity +public class House { + @Id + @GeneratedValue + private Long id; + + private String streetAddress; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getStreetAddress() { + return streetAddress; + } + + public void setStreetAddress(String streetAddress) { + this.streetAddress = streetAddress; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/quote/QuoteGlobalTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/quote/QuoteGlobalTest.java index 23fecfbc72..c179cec84e 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/quote/QuoteGlobalTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/quote/QuoteGlobalTest.java @@ -88,7 +88,8 @@ protected Class[] getAnnotatedClasses() { User.class, Role.class, Phone.class, - Person.class + Person.class, + House.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/quote/QuoteTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/quote/QuoteTest.java index 0eae871336..b5c33e0313 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/quote/QuoteTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/quote/QuoteTest.java @@ -23,18 +23,20 @@ */ package org.hibernate.test.annotations.quote; -import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import org.hibernate.Session; import org.hibernate.Transaction; +import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; - -import static org.junit.Assert.assertEquals; +import org.junit.Test; /** * @author Emmanuel Bernard */ public class QuoteTest extends BaseCoreFunctionalTestCase { + @Test public void testQuoteManytoMany() { Session s = openSession(); @@ -53,13 +55,39 @@ public void testQuoteManytoMany() { assertEquals( "User_Role", configuration().getCollectionMapping( role ).getCollectionTable().getName() ); s.close(); } + + @Test + @TestForIssue(jiraKey = "HHH-8464") + public void testDoubleQuoteJoinColumn() { + Session s = openSession(); + s.getTransaction().begin(); + User user = new User(); + House house = new House(); + user.setHouse( house ); + s.persist( house ); + s.persist( user ); + s.getTransaction().commit(); + s.clear(); + + s = openSession(); + s.getTransaction().begin(); + user = (User) s.get( User.class, user.getId() ); + assertNotNull( user ); + assertNotNull( user.getHouse() ); + // seems trivial, but if quoting normalization worked on the join column, these should all be the same + assertEquals( user.getHouse().getId(), user.getHouse1() ); + assertEquals( user.getHouse().getId(), user.getHouse2() ); + s.getTransaction().commit(); + s.close(); + } @Override protected Class[] getAnnotatedClasses() { return new Class[] { User.class, Role.class, - Phone.class + Phone.class, + House.class }; } } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/quote/User.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/quote/User.java index 9ddc4c5b4c..81794ea94e 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/quote/User.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/quote/User.java @@ -1,13 +1,18 @@ //$Id$ package org.hibernate.test.annotations.quote; + import java.io.Serializable; import java.util.HashSet; import java.util.Set; + +import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; +import javax.persistence.JoinColumn; import javax.persistence.ManyToMany; +import javax.persistence.ManyToOne; import javax.persistence.Table; /** @@ -17,13 +22,23 @@ @Table(name = "`User`") public class User implements Serializable { - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - private long id; + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; - @ManyToMany - private Set roles = new HashSet(); + @ManyToMany + private Set roles = new HashSet(); + // These exist solely for HHH-8464 to ensure that the various forms of quoting are normalized internally + // (using backticks), including the join column. Without normalization, the mapping will throw a + // DuplicateMappingException. + @ManyToOne + @JoinColumn(name = "\"house\"") + private House house; + @Column(name = "\"house\"", insertable = false, updatable = false ) + private Long house1; + @Column(name = "`house`", insertable = false, updatable = false ) + private Long house2; public long getId() { return id; @@ -40,4 +55,28 @@ public Set getRoles() { public void setRoles(Set roles) { this.roles = roles; } + + public House getHouse() { + return house; + } + + public void setHouse(House house) { + this.house = house; + } + + public Long getHouse1() { + return house1; + } + + public void setHouse1(Long house1) { + this.house1 = house1; + } + + public Long getHouse2() { + return house2; + } + + public void setHouse2(Long house2) { + this.house2 = house2; + } }