From 477b239994be77b418983e891a62468db75c6a6c Mon Sep 17 00:00:00 2001 From: Lukasz Antoniak Date: Fri, 15 Feb 2013 15:49:00 +0100 Subject: [PATCH] HHH-7608 - Fix and test --- .../ordering/antlr/OrderByFragmentParser.java | 4 +- .../test/annotations/onetomany/Box.java | 67 +++++++++++++ .../test/annotations/onetomany/Item.java | 95 +++++++++++++++++++ .../annotations/onetomany/OrderByTest.java | 47 ++++++++- 4 files changed, 210 insertions(+), 3 deletions(-) create mode 100644 hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/Box.java create mode 100644 hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/Item.java diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ordering/antlr/OrderByFragmentParser.java b/hibernate-core/src/main/java/org/hibernate/sql/ordering/antlr/OrderByFragmentParser.java index 90fd42fe37..0ce8d6e10d 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ordering/antlr/OrderByFragmentParser.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ordering/antlr/OrderByFragmentParser.java @@ -228,7 +228,7 @@ public class OrderByFragmentParser extends GeneratedOrderByFragmentParser { private String adjustTemplateReferences(String template) { int templateLength = template.length(); int startPos = template.indexOf( Template.TEMPLATE ); - while ( startPos < templateLength ) { + while ( startPos != -1 && startPos < templateLength ) { int dotPos = startPos + TEMPLATE_MARKER_LENGTH; // from here we need to seek the end of the qualified identifier @@ -246,7 +246,7 @@ public class OrderByFragmentParser extends GeneratedOrderByFragmentParser { columnReferences.add( columnReference ); // prep for the next seek - startPos = ( pos - TEMPLATE_MARKER_LENGTH ) + 1; + startPos = template.indexOf( Template.TEMPLATE, ( pos - TEMPLATE_MARKER_LENGTH ) + 1 ); templateLength = template.length(); } diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/Box.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/Box.java new file mode 100644 index 0000000000..e30d850bfa --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/Box.java @@ -0,0 +1,67 @@ +package org.hibernate.test.annotations.onetomany; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.OrderBy; + +/** + * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) + */ +@Entity +public class Box implements Serializable { + @Id + private int id; + + @OneToMany( mappedBy = "box" ) + @OrderBy( "sortField DESC, code" ) // Sorting by @Formula calculated field. + private List items = new ArrayList(); + + public Box() { + } + + public Box(int id) { + this.id = id; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) return true; + if ( !( o instanceof Box ) ) return false; + + Box box = (Box) o; + + if ( id != box.id ) return false; + + return true; + } + + @Override + public int hashCode() { + return id; + } + + @Override + public String toString() { + return "Box(id = " + id + ")"; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public List getItems() { + return items; + } + + public void setItems(List items) { + this.items = items; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/Item.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/Item.java new file mode 100644 index 0000000000..bfd4191f6e --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/Item.java @@ -0,0 +1,95 @@ +package org.hibernate.test.annotations.onetomany; + +import java.io.Serializable; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +import org.hibernate.annotations.Formula; + +/** + * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) + */ +@Entity +public class Item implements Serializable { + @Id + private int id; + + @Column( name = "code" ) + private String code; + + @Formula( "( SELECT LENGTH( code ) FROM DUAL )" ) + private int sortField; + + @ManyToOne + private Box box; + + public Item() { + } + + public Item(int id, String code, Box box) { + this.id = id; + this.code = code; + this.box = box; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) return true; + if ( !( o instanceof Item ) ) return false; + + Item item = (Item) o; + + if ( id != item.id ) return false; + if ( sortField != item.sortField ) return false; + if ( code != null ? !code.equals( item.code ) : item.code != null ) return false; + + return true; + } + + @Override + public int hashCode() { + int result = id; + result = 31 * result + ( code != null ? code.hashCode() : 0 ); + result = 31 * result + sortField; + return result; + } + + @Override + public String toString() { + return "Item(id = " + id + ", code = " + code + ", sortField = " + sortField + ")"; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public int getSortField() { + return sortField; + } + + public void setSortField(int sortField) { + this.sortField = sortField; + } + + public Box getBox() { + return box; + } + + public void setBox(Box box) { + this.box = box; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/OrderByTest.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/OrderByTest.java index 3f923434fc..3bc9fcd100 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/OrderByTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/annotations/onetomany/OrderByTest.java @@ -35,6 +35,7 @@ import org.hibernate.NullPrecedence; import org.hibernate.Session; import org.hibernate.dialect.H2Dialect; import org.hibernate.dialect.MySQLDialect; +import org.hibernate.dialect.Oracle8iDialect; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; @@ -263,8 +264,52 @@ public class OrderByTest extends BaseCoreFunctionalTestCase { session.close(); } + @Test + @TestForIssue( jiraKey = "HHH-7608" ) + @RequiresDialect({ H2Dialect.class, Oracle8iDialect.class }) + public void testOrderByReferencingFormulaColumn() { + Session session = openSession(); + + // Populating database with test data. + session.getTransaction().begin(); + Box box1 = new Box( 1 ); + Item item1 = new Item( 1, "1", box1 ); + Item item2 = new Item( 2, "22", box1 ); + Item item3 = new Item( 3, "2", box1 ); + session.persist( box1 ); + session.persist( item1 ); + session.persist( item2 ); + session.persist( item3 ); + session.flush(); + session.refresh( item1 ); + session.refresh( item2 ); + session.refresh( item3 ); + session.getTransaction().commit(); + + session.clear(); + + session.getTransaction().begin(); + box1 = (Box) session.get( Box.class, box1.getId() ); + Assert.assertEquals( Arrays.asList( item2, item1, item3 ), box1.getItems() ); + session.getTransaction().commit(); + + session.clear(); + + // Cleanup data. + session.getTransaction().begin(); + session.delete( item1 ); + session.delete( item2 ); + session.delete( item3 ); + session.delete( box1 ); + session.getTransaction().commit(); + + session.close(); + } + @Override protected Class[] getAnnotatedClasses() { - return new Class[] { Order.class, OrderItem.class, Zoo.class, Tiger.class, Monkey.class, Visitor.class }; + return new Class[] { + Order.class, OrderItem.class, Zoo.class, Tiger.class, Monkey.class, Visitor.class, Box.class, Item.class + }; } }