Author: sharathjreddy
Date: 2010-02-25 08:12:27 -0500 (Thu, 25 Feb 2010)
New Revision: 18884
Added:
core/trunk/annotations/src/main/java/org/hibernate/annotations/Subselect.java
core/trunk/annotations/src/main/java/org/hibernate/annotations/Synchronize.java
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/subselect/
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/subselect/Bid.java
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/subselect/HighestBid.java
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/subselect/Item.java
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/subselect/SubselectTest.java
Modified:
core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java
core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/TableBinder.java
Log:
HHH-4374 Subselect. Also implemented Synchronize annotation.
Added: core/trunk/annotations/src/main/java/org/hibernate/annotations/Subselect.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/annotations/Subselect.java
(rev 0)
+++
core/trunk/annotations/src/main/java/org/hibernate/annotations/Subselect.java 2010-02-25
13:12:27 UTC (rev 18884)
@@ -0,0 +1,18 @@
+package org.hibernate.annotations;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Map an immutable and read-only entity to a given SQL subselect expression:
+ * @author Sharath Reddy
+ *
+ */
+@Target(TYPE)
+@Retention(RUNTIME)
+public @interface Subselect {
+ String value();
+}
Added: core/trunk/annotations/src/main/java/org/hibernate/annotations/Synchronize.java
===================================================================
--- core/trunk/annotations/src/main/java/org/hibernate/annotations/Synchronize.java
(rev 0)
+++
core/trunk/annotations/src/main/java/org/hibernate/annotations/Synchronize.java 2010-02-25
13:12:27 UTC (rev 18884)
@@ -0,0 +1,21 @@
+package org.hibernate.annotations;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Ensures that auto-flush happens correctly and that queries against the derived
+ * entity do not return stale data.
+ *
+ * Mostly used with Subselect.
+ *
+ * @author Sharath Reddy
+ */
+@Target(TYPE)
+@Retention(RUNTIME)
+public @interface Synchronize {
+ String [] value();
+}
Modified:
core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java
===================================================================
---
core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java 2010-02-25
10:44:48 UTC (rev 18883)
+++
core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/EntityBinder.java 2010-02-25
13:12:27 UTC (rev 18884)
@@ -54,6 +54,8 @@
import org.hibernate.annotations.SQLDeleteAll;
import org.hibernate.annotations.SQLInsert;
import org.hibernate.annotations.SQLUpdate;
+import org.hibernate.annotations.Subselect;
+import org.hibernate.annotations.Synchronize;
import org.hibernate.annotations.Tables;
import org.hibernate.annotations.Tuplizer;
import org.hibernate.annotations.Tuplizers;
@@ -120,7 +122,9 @@
private boolean cacheLazyProperty;
private AccessType propertyAccessType = AccessType.DEFAULT;
private boolean wrapIdsInEmbeddedComponents;
-
+ private String subselect;
+
+
public boolean wrapIdsInEmbeddedComponents() {
return wrapIdsInEmbeddedComponents;
}
@@ -257,6 +261,7 @@
SQLDelete sqlDelete = annotatedClass.getAnnotation( SQLDelete.class );
SQLDeleteAll sqlDeleteAll = annotatedClass.getAnnotation( SQLDeleteAll.class );
Loader loader = annotatedClass.getAnnotation( Loader.class );
+
if ( sqlInsert != null ) {
persistentClass.setCustomSQLInsert( sqlInsert.sql().trim(), sqlInsert.callable(),
ExecuteUpdateResultCheckStyle.parse( sqlInsert.check().toString().toLowerCase() )
@@ -282,6 +287,20 @@
persistentClass.setLoaderName( loader.namedQuery() );
}
+ if ( annotatedClass.isAnnotationPresent( Synchronize.class )) {
+ Synchronize synchronizedWith = annotatedClass.getAnnotation(Synchronize.class);
+
+ String [] tables = synchronizedWith.value();
+ for (String table : tables) {
+ persistentClass.addSynchronizedTable(table);
+ }
+ }
+
+ if ( annotatedClass.isAnnotationPresent(Subselect.class )) {
+ Subselect subselect = annotatedClass.getAnnotation(Subselect.class);
+ this.subselect = subselect.value();
+ }
+
//tuplizers
if ( annotatedClass.isAnnotationPresent( Tuplizers.class ) ) {
for (Tuplizer tuplizer : annotatedClass.getAnnotation( Tuplizers.class ).value()) {
@@ -474,7 +493,8 @@
uniqueConstraints,
constraints,
denormalizedSuperclassTable,
- mappings
+ mappings,
+ this.subselect
);
if ( persistentClass instanceof TableOwner ) {
@@ -701,7 +721,8 @@
uniqueConstraintHolders,
null,
null,
- mappings
+ mappings,
+ null
);
//no check constraints available on joins
Modified:
core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/TableBinder.java
===================================================================
---
core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/TableBinder.java 2010-02-25
10:44:48 UTC (rev 18883)
+++
core/trunk/annotations/src/main/java/org/hibernate/cfg/annotations/TableBinder.java 2010-02-25
13:12:27 UTC (rev 18884)
@@ -183,7 +183,8 @@
uniqueConstraints,
constraints,
denormalizedSuperTable,
- mappings
+ mappings,
+ null
);
}
@@ -200,7 +201,7 @@
return new AssociationTableNameSource( name, logicalName );
}
-
+
public static Table buildAndFillTable(
String schema,
String catalog,
@@ -210,7 +211,8 @@
List<UniqueConstraintHolder> uniqueConstraints,
String constraints,
Table denormalizedSuperTable,
- ExtendedMappings mappings) {
+ ExtendedMappings mappings,
+ String subselect) {
schema = BinderHelper.isDefault( schema ) ? mappings.getSchemaName() : schema;
catalog = BinderHelper.isDefault( catalog ) ? mappings.getCatalogName() : catalog;
@@ -226,7 +228,7 @@
catalog,
realTableName,
isAbstract,
- null, // subselect
+ subselect,
denormalizedSuperTable
);
}
@@ -235,7 +237,7 @@
schema,
catalog,
realTableName,
- null, // subselect
+ subselect,
isAbstract
);
}
Added:
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/subselect/Bid.java
===================================================================
---
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/subselect/Bid.java
(rev 0)
+++
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/subselect/Bid.java 2010-02-25
13:12:27 UTC (rev 18884)
@@ -0,0 +1,65 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2009, Red Hat, Inc. and/or its affiliates or third-
+ * party contributors as indicated by the @author tags or express
+ * copyright attribution statements applied by the authors.
+ * All third-party contributions are distributed under license by
+ * Red Hat, Inc.
+ *
+ * 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, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY 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 along with this distribution; if not, write to:
+ *
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+package org.hibernate.test.annotations.subselect;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+
+/**
+ * @author Sharath Reddy
+ */
+@Entity
+public class Bid {
+
+ private int id;
+ private long itemId;
+ private double amount;
+
+ @Id
+ public int getId() {
+ return id;
+ }
+ public void setId(int id) {
+ this.id = id;
+ }
+ public long getItemId() {
+ return itemId;
+ }
+ public void setItemId(long itemId) {
+ this.itemId = itemId;
+ }
+ public double getAmount() {
+ return amount;
+ }
+ public void setAmount(double val) {
+ this.amount = val;
+ }
+
+
+
+}
Added:
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/subselect/HighestBid.java
===================================================================
---
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/subselect/HighestBid.java
(rev 0)
+++
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/subselect/HighestBid.java 2010-02-25
13:12:27 UTC (rev 18884)
@@ -0,0 +1,64 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2009, Red Hat, Inc. and/or its affiliates or third-
+ * party contributors as indicated by the @author tags or express
+ * copyright attribution statements applied by the authors.
+ * All third-party contributions are distributed under license by
+ * Red Hat, Inc.
+ *
+ * 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, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY 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 along with this distribution; if not, write to:
+ *
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+
+package org.hibernate.test.annotations.subselect;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+import org.hibernate.annotations.Subselect;
+import org.hibernate.annotations.Synchronize;
+
+/**
+ * @author Sharath Reddy
+ *
+ */
+@Entity
+@Subselect("select item.name as name, max(bid.amount) as amount from item, bid where
bid.itemId = item.id group by item.name")
+@Synchronize({"Item", "Bid"})
+public class HighestBid {
+
+ private String name;
+ private double amount;
+
+ @Id
+ public String getName() {
+ return name;
+ }
+ public void setName(String val) {
+ this.name = val;
+ }
+ public double getAmount() {
+ return amount;
+ }
+ public void setAmount(double amount) {
+ this.amount = amount;
+ }
+
+
+
+}
Added:
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/subselect/Item.java
===================================================================
---
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/subselect/Item.java
(rev 0)
+++
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/subselect/Item.java 2010-02-25
13:12:27 UTC (rev 18884)
@@ -0,0 +1,58 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2009, Red Hat, Inc. and/or its affiliates or third-
+ * party contributors as indicated by the @author tags or express
+ * copyright attribution statements applied by the authors.
+ * All third-party contributions are distributed under license by
+ * Red Hat, Inc.
+ *
+ * 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, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY 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 along with this distribution; if not, write to:
+ *
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+
+package org.hibernate.test.annotations.subselect;
+
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+/**
+ * @author Sharath Reddy
+ */
+@Entity
+public class Item {
+
+ private long id;
+ private String name;
+
+ @Id
+ public long getId() {
+ return id;
+ }
+ public void setId(long id) {
+ this.id = id;
+ }
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+
+
+}
Added:
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/subselect/SubselectTest.java
===================================================================
---
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/subselect/SubselectTest.java
(rev 0)
+++
core/trunk/annotations/src/test/java/org/hibernate/test/annotations/subselect/SubselectTest.java 2010-02-25
13:12:27 UTC (rev 18884)
@@ -0,0 +1,89 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2009, Red Hat, Inc. and/or its affiliates or third-
+ * party contributors as indicated by the @author tags or express
+ * copyright attribution statements applied by the authors.
+ * All third-party contributions are distributed under license by
+ * Red Hat, Inc.
+ *
+ * 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, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY 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 along with this distribution; if not, write to:
+ *
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA 02110-1301 USA
+ */
+
+package org.hibernate.test.annotations.subselect;
+
+import org.hibernate.Hibernate;
+import org.hibernate.Query;
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+import org.hibernate.test.annotations.TestCase;
+
+
+/**
+ * @author Sharath Reddy
+ */
+public class SubselectTest extends TestCase {
+
+ public void testSubselectWithSynchronize() {
+
+ Session s = openSession();
+ Transaction tx = s.beginTransaction();
+ tx.begin();
+
+ //We don't use auto-generated ids because these seem to cause the session to
flush.
+ //We want to test that the session flushes because of the 'synchronize'
annotation
+ long itemId = 1;
+ Item item = new Item();
+ item.setName("widget");
+ item.setId(itemId);
+ s.save(item);
+
+ Bid bid1 = new Bid();
+ bid1.setAmount(100.0);
+ bid1.setItemId(itemId);
+ bid1.setId(1);
+ s.save(bid1);
+
+ Bid bid2 = new Bid();
+ bid2.setAmount(200.0);
+ bid2.setItemId(itemId);
+ bid2.setId(2);
+ s.save(bid2);
+
+ //Because we use 'synchronize' annotation, this query should trigger session
flush
+ Query query = s.createQuery("from HighestBid b where b.name = :name");
+ query.setParameter("name", "widget", Hibernate.STRING);
+ HighestBid highestBid = (HighestBid) query.list().iterator().next();
+
+ assertEquals(200.0, highestBid.getAmount());
+
+ s.close();
+
+
+ }
+
+ @Override
+ protected Class<?>[] getAnnotatedClasses() {
+ return new Class[]{
+ Item.class,
+ Bid.class,
+ HighestBid.class
+ };
+ }
+
+}