HHH-10603 Avoid doing distinct and comparisons on byte arrays

They are stored as blobs starting with Oracle12cDialect and distinct and
comparisons on blobs are not supported.

Some tests were adapted, some are now skipped with Oracle12cDialect.

(cherry picked from commit 92f194f291)
This commit is contained in:
Guillaume Smet 2018-07-31 18:34:27 +02:00 committed by Gail Badner
parent 23a3c0a259
commit 1deccc5426
7 changed files with 203 additions and 39 deletions

View File

@ -61,6 +61,7 @@ import org.hibernate.dialect.HSQLDialect;
import org.hibernate.dialect.InterbaseDialect;
import org.hibernate.dialect.MckoiDialect;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.Oracle12cDialect;
import org.hibernate.dialect.Oracle8iDialect;
import org.hibernate.dialect.PointbaseDialect;
import org.hibernate.dialect.PostgreSQL81Dialect;
@ -1646,7 +1647,7 @@ public class FooBarTest extends LegacyTestCase {
count++;
}
assertEquals(4, count);
iter = s.createQuery("select distinct foo from Foo foo")
iter = s.createQuery("select foo from Foo foo")
.setMaxResults(2)
.setFirstResult(2)
.list()
@ -1657,7 +1658,7 @@ public class FooBarTest extends LegacyTestCase {
count++;
}
assertTrue(count==2);
iter = s.createQuery("select distinct foo from Foo foo")
iter = s.createQuery("select foo from Foo foo")
.setMaxResults(3)
.list()
.iterator();
@ -2514,7 +2515,9 @@ public class FooBarTest extends LegacyTestCase {
).list();
assertTrue( "collection.elements find", list.size()==2 );
}
if (!(getDialect() instanceof SAPDBDialect) ) { // SAPDB doesn't like distinct with binary type
// SAPDB doesn't like distinct with binary type
// Oracle12cDialect stores binary types as blobs and do no support distinct on blobs
if ( !(getDialect() instanceof SAPDBDialect) && !(getDialect() instanceof Oracle12cDialect) ) {
List list = s.createQuery( "select distinct foo from Baz baz join baz.fooArray foo" ).list();
assertTrue( "collection.elements find", list.size()==2 );
}

View File

@ -26,8 +26,8 @@ public class MultiTypedBasicAttributesEntity {
@GeneratedValue( generator = "increment" )
@GenericGenerator( name = "increment", strategy = "increment" )
private Long id;
private byte[] someBytes;
private Byte[] someWrappedBytes;
private int[] someInts;
private Integer[] someWrappedIntegers;
public Long getId() {
return id;
@ -37,19 +37,19 @@ public class MultiTypedBasicAttributesEntity {
this.id = id;
}
public byte[] getSomeBytes() {
return someBytes;
public int[] getSomeInts() {
return someInts;
}
public void setSomeBytes(byte[] someBytes) {
this.someBytes = someBytes;
public void setSomeInts(int[] someInts) {
this.someInts = someInts;
}
public Byte[] getSomeWrappedBytes() {
return someWrappedBytes;
public Integer[] getSomeWrappedIntegers() {
return someWrappedIntegers;
}
public void setSomeWrappedBytes(Byte[] someWrappedBytes) {
this.someWrappedBytes = someWrappedBytes;
public void setSomeWrappedIntegers(Integer[] someWrappedIntegers) {
this.someWrappedIntegers = someWrappedIntegers;
}
}

View File

@ -34,12 +34,12 @@ public class ParameterTest extends BaseEntityManagerFunctionalTestCase {
CriteriaQuery<MultiTypedBasicAttributesEntity> criteria = em.getCriteriaBuilder()
.createQuery( MultiTypedBasicAttributesEntity.class );
Root<MultiTypedBasicAttributesEntity> rootEntity = criteria.from( MultiTypedBasicAttributesEntity.class );
Path<byte[]> someBytesPath = rootEntity.get( MultiTypedBasicAttributesEntity_.someBytes );
ParameterExpression<byte[]> param = em.getCriteriaBuilder().parameter( byte[].class, "theBytes" );
criteria.where( em.getCriteriaBuilder().equal( someBytesPath, param ) );
Path<int[]> someIntsPath = rootEntity.get( MultiTypedBasicAttributesEntity_.someInts );
ParameterExpression<int[]> param = em.getCriteriaBuilder().parameter( int[].class, "theInts" );
criteria.where( em.getCriteriaBuilder().equal( someIntsPath, param ) );
TypedQuery<MultiTypedBasicAttributesEntity> query = em.createQuery( criteria );
query.setParameter( param, new byte[] { 1,1,1 } );
assertThat( query.getParameterValue( param.getName() ), instanceOf( byte[].class) );
query.setParameter( param, new int[] { 1,1,1 } );
assertThat( query.getParameterValue( param.getName() ), instanceOf( int[].class) );
query.getResultList();
em.getTransaction().commit();
em.close();
@ -52,12 +52,12 @@ public class ParameterTest extends BaseEntityManagerFunctionalTestCase {
CriteriaQuery<MultiTypedBasicAttributesEntity> criteria = em.getCriteriaBuilder()
.createQuery( MultiTypedBasicAttributesEntity.class );
Root<MultiTypedBasicAttributesEntity> rootEntity = criteria.from( MultiTypedBasicAttributesEntity.class );
Path<Byte[]> thePath = rootEntity.get( MultiTypedBasicAttributesEntity_.someWrappedBytes );
ParameterExpression<Byte[]> param = em.getCriteriaBuilder().parameter( Byte[].class, "theBytes" );
Path<Integer[]> thePath = rootEntity.get( MultiTypedBasicAttributesEntity_.someWrappedIntegers );
ParameterExpression<Integer[]> param = em.getCriteriaBuilder().parameter( Integer[].class, "theIntegers" );
criteria.where( em.getCriteriaBuilder().equal( thePath, param ) );
TypedQuery<MultiTypedBasicAttributesEntity> query = em.createQuery( criteria );
query.setParameter( param, new Byte[] { Byte.valueOf((byte)1), Byte.valueOf((byte)1), Byte.valueOf((byte)1) } );
assertThat( query.getParameterValue( param.getName() ), instanceOf( Byte[].class ) );
query.setParameter( param, new Integer[] { Integer.valueOf(1), Integer.valueOf(1), Integer.valueOf(1) } );
assertThat( query.getParameterValue( param.getName() ), instanceOf( Integer[].class ) );
query.getResultList();
em.getTransaction().commit();
em.close();

View File

@ -6,7 +6,11 @@
*/
package org.hibernate.jpa.test.criteria.basic;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
@ -14,20 +18,20 @@ import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.junit.Before;
import org.junit.Test;
import org.hibernate.dialect.Oracle12cDialect;
import org.hibernate.dialect.Oracle8iDialect;
import org.hibernate.dialect.Oracle9Dialect;
import org.hibernate.dialect.OracleDialect;
import org.hibernate.jpa.test.metamodel.AbstractMetamodelSpecificTest;
import org.hibernate.jpa.test.metamodel.CreditCard;
import org.hibernate.jpa.test.metamodel.CreditCard_;
import org.hibernate.jpa.test.metamodel.Customer_;
import org.hibernate.jpa.test.metamodel.Order;
import org.hibernate.jpa.test.metamodel.Order_;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.TestForIssue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.Test;
/**
* Test the various predicates.
@ -211,7 +215,7 @@ public class PredicateTest extends AbstractMetamodelSpecificTest {
em.getTransaction().begin();
CriteriaQuery<Order> orderCriteria = builder.createQuery( Order.class );
Root<Order> orderRoot = orderCriteria.from( Order.class );
orderCriteria.select( orderRoot );
Predicate p = builder.equal( orderRoot.get( "domen" ), new char[]{'r','u'} );
orderCriteria.where( p );
@ -223,15 +227,17 @@ public class PredicateTest extends AbstractMetamodelSpecificTest {
}
/**
* Check predicate for field which has simple char array type (byte[]).
* Check predicate for field which has simple byte array type (byte[]).
*/
@Test
@SkipForDialect(value = Oracle12cDialect.class, jiraKey = "HHH-10603",
comment = "Oracle12cDialect uses blob to store byte arrays and it's not possible to compare blobs with simple equality operators.")
public void testByteArray() {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
CriteriaQuery<Order> orderCriteria = builder.createQuery( Order.class );
Root<Order> orderRoot = orderCriteria.from( Order.class );
orderCriteria.select( orderRoot );
Predicate p = builder.equal( orderRoot.get( "number" ), new byte[]{'1','2'} );
orderCriteria.where( p );

View File

@ -13,18 +13,19 @@ import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.Root;
import org.hibernate.jpa.test.metamodel.AbstractMetamodelSpecificTest;
import org.hibernate.jpa.test.metamodel.LineItem;
import org.hibernate.jpa.test.metamodel.LineItem_;
import org.hibernate.jpa.test.metamodel.Order;
import org.hibernate.jpa.test.metamodel.Order_;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.junit.Test;
/**
* @author Steve Ebersole
*/
public class ImplicitJoinTest extends AbstractMetamodelSpecificTest {
public class ImplicitJoinTest extends BaseEntityManagerFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { Order.class, LineItem.class };
}
@Test
public void testImplicitJoinFromExplicitCollectionJoin() {
EntityManager em = getOrCreateEntityManager();

View File

@ -0,0 +1,66 @@
/*
* 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.jpa.test.criteria.paths;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name = "LINEITEM_TABLE")
public class LineItem {
private String id;
private int quantity;
private Order order;
public LineItem() {
}
public LineItem(String v1, int v2, Order v3) {
id = v1;
quantity = v2;
order = v3;
}
public LineItem(String v1, int v2) {
id = v1;
quantity = v2;
}
@Id
@Column(name = "ID")
public String getId() {
return id;
}
public void setId(String v) {
id = v;
}
@Column(name = "QUANTITY")
public int getQuantity() {
return quantity;
}
public void setQuantity(int v) {
quantity = v;
}
@ManyToOne
@JoinColumn(name = "FK1_FOR_ORDER_TABLE")
public Order getOrder() {
return order;
}
public void setOrder(Order v) {
order = v;
}
}

View File

@ -0,0 +1,88 @@
/*
* 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.jpa.test.criteria.paths;
import java.util.Collection;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
@Entity
@Table(name = "ORDER_TABLE")
public class Order {
private String id;
private double totalPrice;
private LineItem sampleLineItem;
private Collection<LineItem> lineItems = new java.util.ArrayList<LineItem>();
public Order() {
}
public Order(String id, double totalPrice) {
this.id = id;
this.totalPrice = totalPrice;
}
public Order(String id) {
this.id = id;
}
// ====================================================================
// getters and setters for State fields
@Id
@Column(name = "ID")
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Column(name = "TOTALPRICE")
public double getTotalPrice() {
return totalPrice;
}
public void setTotalPrice(double price) {
this.totalPrice = price;
}
// ====================================================================
// getters and setters for Association fields
// 1x1
@OneToOne(cascade = CascadeType.REMOVE)
@JoinColumn(name = "FK0_FOR_LINEITEM_TABLE")
public LineItem getSampleLineItem() {
return sampleLineItem;
}
public void setSampleLineItem(LineItem l) {
this.sampleLineItem = l;
}
// 1xMANY
@OneToMany(cascade = CascadeType.ALL, mappedBy = "order")
public Collection<LineItem> getLineItems() {
return lineItems;
}
public void setLineItems(Collection<LineItem> c) {
this.lineItems = c;
}
}