merge master
This commit is contained in:
commit
5d114797e1
|
@ -23,8 +23,13 @@
|
|||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter;
|
||||
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
|
||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||
|
||||
/**
|
||||
* An SQL dialect for MySQL 5.x specific features.
|
||||
*
|
||||
|
@ -43,4 +48,27 @@ public class MySQL5Dialect extends MySQLDialect {
|
|||
public boolean supportsColumnCheck() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public ViolatedConstraintNameExtracter getViolatedConstraintNameExtracter() {
|
||||
return EXTRACTER;
|
||||
}
|
||||
|
||||
private static final ViolatedConstraintNameExtracter EXTRACTER = new TemplatedViolatedConstraintNameExtracter() {
|
||||
|
||||
public String extractConstraintName(SQLException sqle) {
|
||||
try {
|
||||
final int sqlState = Integer.valueOf( JdbcExceptionHelper.extractSqlState( sqle ) ).intValue();
|
||||
switch ( sqlState ) {
|
||||
case 23000:
|
||||
return extractUsingTemplate( " for key '", "'", sqle.getMessage() );
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch ( NumberFormatException nfe ) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -421,7 +421,9 @@ public class JdbcCoordinatorImpl implements JdbcCoordinator {
|
|||
}
|
||||
}
|
||||
if ( statement != null ) {
|
||||
if ( LOG.isEnabled( Level.WARN ) && !xref.containsKey( statement ) ) {
|
||||
// Keep this at DEBUG level, rather than warn. Numerous connection pool implementations can return a
|
||||
// proxy/wrapper around the JDBC Statement, causing excessive logging here. See HHH-8210.
|
||||
if ( LOG.isEnabled( Level.DEBUG ) && !xref.containsKey( statement ) ) {
|
||||
LOG.unregisteredStatement();
|
||||
}
|
||||
Set<ResultSet> resultSets = xref.get( statement );
|
||||
|
@ -448,7 +450,9 @@ public class JdbcCoordinatorImpl implements JdbcCoordinator {
|
|||
}
|
||||
}
|
||||
if ( statement != null ) {
|
||||
if ( LOG.isEnabled( Level.WARN ) && !xref.containsKey( statement ) ) {
|
||||
// Keep this at DEBUG level, rather than warn. Numerous connection pool implementations can return a
|
||||
// proxy/wrapper around the JDBC Statement, causing excessive logging here. See HHH-8210.
|
||||
if ( LOG.isEnabled( Level.DEBUG ) && !xref.containsKey( statement ) ) {
|
||||
LOG.unregisteredStatement();
|
||||
}
|
||||
final Set<ResultSet> resultSets = xref.get( statement );
|
||||
|
|
|
@ -38,6 +38,7 @@ import org.hibernate.internal.CoreMessageLogger;
|
|||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.persister.collection.QueryableCollection;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.Queryable;
|
||||
import org.hibernate.sql.JoinFragment;
|
||||
import org.hibernate.sql.JoinType;
|
||||
import org.hibernate.type.CollectionType;
|
||||
|
@ -282,19 +283,36 @@ public class DotNode extends FromReferenceNode implements DisplayableNode, Selec
|
|||
String propName = getPath();
|
||||
FromClause currentFromClause = getWalker().getCurrentFromClause();
|
||||
|
||||
if ( getWalker().getStatementType() != SqlTokenTypes.SELECT && indexed && classAlias == null ) {
|
||||
// should indicate that we are processing an INSERT/UPDATE/DELETE
|
||||
// query with a subquery implied via a collection property
|
||||
// function. Here, we need to use the table name itself as the
|
||||
// qualification alias.
|
||||
// TODO : verify this works for all databases...
|
||||
// TODO : is this also the case in non-"indexed" scenarios?
|
||||
String alias = getLhs().getFromElement().getQueryable().getTableName();
|
||||
columns = getFromElement().toColumns( alias, propertyPath, false, true );
|
||||
// determine whether we should use the table name or table alias to qualify the column names...
|
||||
// we need to use the table-name when:
|
||||
// 1) the top-level statement is not a SELECT
|
||||
// 2) the LHS FromElement is *the* FromElement from the top-level statement
|
||||
//
|
||||
// there is a caveat here.. if the update/delete statement are "multi-table" we should continue to use
|
||||
// the alias also, even if the FromElement is the root one...
|
||||
//
|
||||
// in all other cases, we should use the table alias
|
||||
final FromElement lhsFromElement = getLhs().getFromElement();
|
||||
if ( getWalker().getStatementType() != SqlTokenTypes.SELECT ) {
|
||||
if ( isFromElementUpdateOrDeleteRoot( lhsFromElement ) ) {
|
||||
// at this point we know we have the 2 conditions above,
|
||||
// lets see if we have the mentioned "multi-table" caveat...
|
||||
boolean useAlias = false;
|
||||
if ( getWalker().getStatementType() != SqlTokenTypes.INSERT ) {
|
||||
final Queryable persister = lhsFromElement.getQueryable();
|
||||
if ( persister.isMultiTable() ) {
|
||||
useAlias = true;
|
||||
}
|
||||
}
|
||||
if ( ! useAlias ) {
|
||||
final String lhsTableName = lhsFromElement.getQueryable().getTableName();
|
||||
columns = getFromElement().toColumns( lhsTableName, propertyPath, false, true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//We do not look for an existing join on the same path, because
|
||||
//it makes sense to join twice on the same collection role
|
||||
// We do not look for an existing join on the same path, because
|
||||
// it makes sense to join twice on the same collection role
|
||||
FromElementFactory factory = new FromElementFactory(
|
||||
currentFromClause,
|
||||
getLhs().getFromElement(),
|
||||
|
|
|
@ -27,6 +27,7 @@ import antlr.SemanticException;
|
|||
import antlr.collections.AST;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.hql.internal.antlr.HqlSqlTokenTypes;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
/**
|
||||
|
@ -130,4 +131,15 @@ public abstract class FromReferenceNode extends AbstractSelectExpression
|
|||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("SimplifiableIfStatement")
|
||||
protected boolean isFromElementUpdateOrDeleteRoot(FromElement element) {
|
||||
if ( element.getFromClause().getParentFromClause() != null ) {
|
||||
// its not even a root...
|
||||
return false;
|
||||
}
|
||||
|
||||
return getWalker().getStatementType() == HqlSqlTokenTypes.DELETE
|
||||
|| getWalker().getStatementType() == HqlSqlTokenTypes.UPDATE;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -150,42 +150,54 @@ public class IdentNode extends FromReferenceNode implements SelectExpression {
|
|||
|
||||
private boolean resolveAsAlias() {
|
||||
// This is not actually a constant, but a reference to FROM element.
|
||||
FromElement element = getWalker().getCurrentFromClause().getFromElement( getText() );
|
||||
if ( element != null ) {
|
||||
setType( SqlTokenTypes.ALIAS_REF );
|
||||
setFromElement( element );
|
||||
String[] columnExpressions = element.getIdentityColumns();
|
||||
final boolean isInNonDistinctCount = getWalker().isInCount() && ! getWalker().isInCountDistinct();
|
||||
final boolean isCompositeValue = columnExpressions.length > 1;
|
||||
if ( isCompositeValue ) {
|
||||
if ( isInNonDistinctCount && ! getWalker().getSessionFactoryHelper().getFactory().getDialect().supportsTupleCounts() ) {
|
||||
setText( columnExpressions[0] );
|
||||
}
|
||||
else {
|
||||
String joinedFragment = StringHelper.join( ", ", columnExpressions );
|
||||
// avoid wrapping in parenthesis (explicit tuple treatment) if possible due to varied support for
|
||||
// tuple syntax across databases..
|
||||
final boolean shouldSkipWrappingInParenthesis =
|
||||
getWalker().isInCount()
|
||||
|| getWalker().getCurrentTopLevelClauseType() == HqlSqlTokenTypes.ORDER
|
||||
|| getWalker().getCurrentTopLevelClauseType() == HqlSqlTokenTypes.GROUP;
|
||||
if ( ! shouldSkipWrappingInParenthesis ) {
|
||||
joinedFragment = "(" + joinedFragment + ")";
|
||||
}
|
||||
setText( joinedFragment );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if ( columnExpressions.length > 0 ) {
|
||||
setText( columnExpressions[0] );
|
||||
return true;
|
||||
final FromElement element = getWalker().getCurrentFromClause().getFromElement( getText() );
|
||||
if ( element == null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
setType( SqlTokenTypes.ALIAS_REF );
|
||||
setFromElement( element );
|
||||
|
||||
String[] columnExpressions = element.getIdentityColumns();
|
||||
|
||||
// determine whether to apply qualification (table alias) to the column(s)...
|
||||
if ( ! isFromElementUpdateOrDeleteRoot( element ) ) {
|
||||
if ( StringHelper.isNotEmpty( element.getTableAlias() ) ) {
|
||||
// apparently we also need to check that they are not already qualified. Ugh!
|
||||
columnExpressions = StringHelper.qualifyIfNot( element.getTableAlias(), columnExpressions );
|
||||
}
|
||||
}
|
||||
|
||||
final boolean isInNonDistinctCount = getWalker().isInCount() && ! getWalker().isInCountDistinct();
|
||||
final boolean isCompositeValue = columnExpressions.length > 1;
|
||||
if ( isCompositeValue ) {
|
||||
if ( isInNonDistinctCount && ! getWalker().getSessionFactoryHelper().getFactory().getDialect().supportsTupleCounts() ) {
|
||||
setText( columnExpressions[0] );
|
||||
}
|
||||
else {
|
||||
String joinedFragment = StringHelper.join( ", ", columnExpressions );
|
||||
// avoid wrapping in parenthesis (explicit tuple treatment) if possible due to varied support for
|
||||
// tuple syntax across databases..
|
||||
final boolean shouldSkipWrappingInParenthesis =
|
||||
getWalker().isInCount()
|
||||
|| getWalker().getCurrentTopLevelClauseType() == HqlSqlTokenTypes.ORDER
|
||||
|| getWalker().getCurrentTopLevelClauseType() == HqlSqlTokenTypes.GROUP;
|
||||
if ( ! shouldSkipWrappingInParenthesis ) {
|
||||
joinedFragment = "(" + joinedFragment + ")";
|
||||
}
|
||||
setText( joinedFragment );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if ( columnExpressions.length > 0 ) {
|
||||
setText( columnExpressions[0] );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private Type getNakedPropertyType(FromElement fromElement)
|
||||
{
|
||||
private Type getNakedPropertyType(FromElement fromElement) {
|
||||
if (fromElement == null) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -1342,7 +1342,9 @@ public interface CoreMessageLogger extends BasicLogger {
|
|||
@Message(value = "ResultSet had no statement associated with it, but was not yet registered", id = 386)
|
||||
void unregisteredResultSetWithoutStatement();
|
||||
|
||||
@LogMessage(level = WARN)
|
||||
// Keep this at DEBUG level, rather than warn. Numerous connection pool implementations can return a
|
||||
// proxy/wrapper around the JDBC Statement, causing excessive logging here. See HHH-8210.
|
||||
@LogMessage(level = DEBUG)
|
||||
@Message(value = "ResultSet's statement was not registered", id = 387)
|
||||
void unregisteredStatement();
|
||||
|
||||
|
|
|
@ -465,7 +465,9 @@ public final class StringHelper {
|
|||
}
|
||||
|
||||
public static String[] qualify(String prefix, String[] names) {
|
||||
if ( prefix == null ) return names;
|
||||
if ( prefix == null ) {
|
||||
return names;
|
||||
}
|
||||
int len = names.length;
|
||||
String[] qualified = new String[len];
|
||||
for ( int i = 0; i < len; i++ ) {
|
||||
|
@ -473,6 +475,24 @@ public final class StringHelper {
|
|||
}
|
||||
return qualified;
|
||||
}
|
||||
|
||||
public static String[] qualifyIfNot(String prefix, String[] names) {
|
||||
if ( prefix == null ) {
|
||||
return names;
|
||||
}
|
||||
int len = names.length;
|
||||
String[] qualified = new String[len];
|
||||
for ( int i = 0; i < len; i++ ) {
|
||||
if ( names[i].indexOf( '.' ) < 0 ) {
|
||||
qualified[i] = qualify( prefix, names[i] );
|
||||
}
|
||||
else {
|
||||
qualified[i] = names[i];
|
||||
}
|
||||
}
|
||||
return qualified;
|
||||
}
|
||||
|
||||
public static int firstIndexOfChar(String sqlString, BitSet keys, int startindex) {
|
||||
for ( int i = startindex, size = sqlString.length(); i < size; i++ ) {
|
||||
if ( keys.get( sqlString.charAt( i ) ) ) {
|
||||
|
|
|
@ -205,6 +205,16 @@ public abstract class AbstractEntityJoinWalker extends JoinWalker {
|
|||
public final String getAlias() {
|
||||
return alias;
|
||||
}
|
||||
|
||||
/**
|
||||
* For entities, orderings added by, for example, Criteria#addOrder need to come before the associations' @OrderBy
|
||||
* values. However, other sub-classes of JoinWalker (BasicCollectionJoinWalker, OneToManyJoinWalker, etc.)
|
||||
* still need the other way around. So, override here instead. See HHH-7116.
|
||||
*/
|
||||
@Override
|
||||
protected String orderBy(final List associations, final String orderBy) {
|
||||
return mergeOrderings( orderBy, orderBy( associations ) );
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getClass().getName() + '(' + getPersister().getEntityName() + ')';
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
package org.hibernate.test.annotations.id;
|
||||
|
||||
import org.hibernate.test.annotations.id.entities.Hotel;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.Session;
|
||||
|
@ -50,12 +51,51 @@ import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
|||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
/**
|
||||
* @author Emmanuel Bernard
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class IdTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
@Test
|
||||
public void testNoGenerator() throws Exception {
|
||||
Session s = openSession();
|
||||
Transaction tx = s.beginTransaction();
|
||||
Hotel hotel = new Hotel();
|
||||
hotel.setId( 12l );
|
||||
hotel.setName("California");
|
||||
s.saveOrUpdate(hotel);
|
||||
tx.commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
tx = s.beginTransaction();
|
||||
hotel = (Hotel) s.get(Hotel.class, 12l);
|
||||
assertNotNull(hotel);
|
||||
assertEquals("California", hotel.getName());
|
||||
assertNull(s.get(Hotel.class, 13l));
|
||||
tx.commit();
|
||||
|
||||
s = openSession();
|
||||
tx = s.beginTransaction();
|
||||
//hotel is now detached
|
||||
hotel.setName("Hotel du nord");
|
||||
s.saveOrUpdate(hotel);
|
||||
tx.commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
tx = s.beginTransaction();
|
||||
hotel = (Hotel) s.get(Hotel.class, 12l);
|
||||
assertNotNull(hotel);
|
||||
assertEquals("Hotel du nord", hotel.getName());
|
||||
s.delete(hotel);
|
||||
tx.commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenericGenerator() throws Exception {
|
||||
Session s = openSession();
|
||||
|
@ -319,7 +359,7 @@ public class IdTest extends BaseCoreFunctionalTestCase {
|
|||
Department.class, Dog.class, Computer.class, Home.class,
|
||||
Phone.class, Tree.class, FirTree.class, Footballer.class,
|
||||
SoundSystem.class, Furniture.class, GoalKeeper.class,
|
||||
BreakDance.class, Monkey.class};
|
||||
BreakDance.class, Monkey.class, Hotel.class };
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package org.hibernate.test.annotations.id.entities;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
|
||||
/**
|
||||
* Entity with assigned identity
|
||||
*
|
||||
* @author Emmanuel Bernard <emmanuel@hibernate.org>
|
||||
*/
|
||||
@Entity
|
||||
public class Hotel {
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package org.hibernate.test.annotations.query;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.OneToMany;
|
||||
|
||||
@Entity
|
||||
public class Attrset {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
@OneToMany
|
||||
@JoinTable(name = "ATTRSET_X_ATTRVALUE")
|
||||
private Set<Attrvalue> attrvalues = new HashSet<Attrvalue>();
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Set<Attrvalue> getAttrvalues() {
|
||||
return attrvalues;
|
||||
}
|
||||
|
||||
public void setAttrvalues(Set<Attrvalue> attrvalues) {
|
||||
this.attrvalues = attrvalues;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package org.hibernate.test.annotations.query;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
|
||||
@Entity
|
||||
public class Attrvalue {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String value;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package org.hibernate.test.annotations.query;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
|
||||
@Entity
|
||||
public class Employee {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
@ManyToOne
|
||||
private Employeegroup employeegroup;
|
||||
|
||||
@ManyToOne
|
||||
private Attrset attrset;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Employeegroup getEmployeegroup() {
|
||||
return employeegroup;
|
||||
}
|
||||
|
||||
public void setEmployeegroup(Employeegroup employeegroup) {
|
||||
this.employeegroup = employeegroup;
|
||||
}
|
||||
|
||||
public Attrset getAttrset() {
|
||||
return attrset;
|
||||
}
|
||||
|
||||
public void setAttrset(Attrset attrset) {
|
||||
this.attrset = attrset;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package org.hibernate.test.annotations.query;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
|
||||
@Entity
|
||||
public class Employeegroup {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL, mappedBy = "employeegroup")
|
||||
private List<Employee> employees = new ArrayList<Employee>();
|
||||
|
||||
@ManyToOne
|
||||
private Attrset attrset;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public List<Employee> getEmployees() {
|
||||
return employees;
|
||||
}
|
||||
|
||||
public void setEmployees(List<Employee> employees) {
|
||||
this.employees = employees;
|
||||
}
|
||||
|
||||
public Attrset getAttrset() {
|
||||
return attrset;
|
||||
}
|
||||
|
||||
public void setAttrset(Attrset attrset) {
|
||||
this.attrset = attrset;
|
||||
}
|
||||
|
||||
}
|
|
@ -51,6 +51,7 @@ import org.hibernate.test.annotations.Plane;
|
|||
import org.hibernate.testing.FailureExpected;
|
||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||
import org.hibernate.testing.SkipForDialect;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -472,7 +473,11 @@ public class QueryAndSQLTest extends BaseCoreFunctionalTestCase {
|
|||
Chaos.class,
|
||||
CasimirParticle.class,
|
||||
AllTables.class,
|
||||
Dimensions.class
|
||||
Dimensions.class,
|
||||
Attrset.class,
|
||||
Attrvalue.class,
|
||||
Employee.class,
|
||||
Employeegroup.class
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package org.hibernate.test.criteria;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author tknowlton at iamhisfriend dot org
|
||||
*/
|
||||
@Entity
|
||||
public class Bid implements Serializable {
|
||||
@Id
|
||||
float amount;
|
||||
|
||||
@Id
|
||||
@ManyToOne
|
||||
Item item;
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* 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.criteria;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.criterion.Projections;
|
||||
import org.hibernate.sql.JoinType;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.hibernate.transform.ResultTransformer;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author tknowlton at iamhisfriend dot org
|
||||
*/
|
||||
public class CriteriaOrderByTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] { Bid.class, Item.class };
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-7116")
|
||||
public void testCriteriaOrderBy() {
|
||||
final Session s = openSession();
|
||||
final Transaction tx = s.beginTransaction();
|
||||
|
||||
Item item;
|
||||
Bid bid;
|
||||
|
||||
item = new Item();
|
||||
item.name = "ZZZZ";
|
||||
s.persist( item );
|
||||
|
||||
bid = new Bid();
|
||||
bid.amount = 444.44f;
|
||||
bid.item = item;
|
||||
s.persist( bid );
|
||||
|
||||
item = new Item();
|
||||
item.name = "AAAA";
|
||||
s.persist( item );
|
||||
|
||||
bid = new Bid();
|
||||
bid.amount = 222.22f;
|
||||
bid.item = item;
|
||||
s.persist( bid );
|
||||
|
||||
item = new Item();
|
||||
item.name = "MMMM";
|
||||
s.persist( item );
|
||||
|
||||
bid = new Bid();
|
||||
bid.amount = 999.99f;
|
||||
bid.item = item;
|
||||
s.persist( bid );
|
||||
|
||||
s.flush();
|
||||
|
||||
// For each item, ordered by name, show all bids made by bidders on this item.
|
||||
// The joined collections item.bids and bidder.bids have orderings specified on the mappings.
|
||||
// For some reason, the association mappings' ordering specifications are not honored if default (INNER) join
|
||||
// type is used.
|
||||
final Criteria criteria = s
|
||||
.createCriteria( Item.class )
|
||||
.addOrder( org.hibernate.criterion.Order.asc( "this.name" ) )
|
||||
.createAlias( "this.bids", "i_bid", JoinType.LEFT_OUTER_JOIN )
|
||||
.setProjection(
|
||||
Projections.projectionList().add( Projections.property( "this.name" ), "item_name" )
|
||||
.add( Projections.property( "i_bid.amount" ), "bid_amount" ) )
|
||||
.setResultTransformer( new ResultTransformer() {
|
||||
boolean first = true;
|
||||
Object[] previous;
|
||||
|
||||
@Override
|
||||
public Object transformTuple(Object[] tuple, String[] aliases) {
|
||||
if ( first ) {
|
||||
first = false;
|
||||
previous = tuple;
|
||||
}
|
||||
else {
|
||||
final String previousName = (String) previous[0];
|
||||
final String name = (String) tuple[0];
|
||||
|
||||
Assert.assertTrue(
|
||||
"The resultset tuples should be ordered by item name, as specified on the Criteria",
|
||||
previousName.compareTo( name ) < 1 );
|
||||
|
||||
previous = tuple;
|
||||
}
|
||||
|
||||
return tuple;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List transformList(List collection) {
|
||||
return collection;
|
||||
}
|
||||
} );
|
||||
|
||||
criteria.list();
|
||||
|
||||
tx.rollback();
|
||||
s.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package org.hibernate.test.criteria;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author tknowlton at iamhisfriend dot org
|
||||
*/
|
||||
@Entity
|
||||
public class Item implements Serializable {
|
||||
@Id
|
||||
String name;
|
||||
|
||||
@OneToMany(mappedBy = "item", fetch = FetchType.EAGER)
|
||||
@OrderBy("amount desc")
|
||||
Set<Bid> bids = new HashSet<Bid>();
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. 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.hql;
|
||||
|
||||
import org.hibernate.Session;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.hibernate.test.annotations.query.Attrset;
|
||||
import org.hibernate.test.annotations.query.Attrvalue;
|
||||
import org.hibernate.test.annotations.query.Employee;
|
||||
import org.hibernate.test.annotations.query.Employeegroup;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class DeleteWhereMemberOfTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class[] getAnnotatedClasses() {
|
||||
return new Class[] {
|
||||
Attrset.class,
|
||||
Attrvalue.class,
|
||||
Employee.class,
|
||||
Employeegroup.class
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-8318" )
|
||||
// @FailureExpected( jiraKey = "HHH-8318" )
|
||||
public void testDeleteMemberOf() {
|
||||
final String qry = "delete Attrvalue aval where aval.id in ( "
|
||||
+ "select val2.id from Employee e, Employeegroup eg, Attrset aset, Attrvalue val2 "
|
||||
+ "where eg.id = e.employeegroup.id " + "and aset.id = e.attrset.id "
|
||||
+ "and val2 member of aset.attrvalues)";
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
s.createQuery( qry ).executeUpdate();
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
}
|
|
@ -51,7 +51,7 @@ ext {
|
|||
dom4j: 'dom4j:dom4j:1.6.1@jar',
|
||||
|
||||
// Javassist
|
||||
javassist: 'org.javassist:javassist:3.15.0-GA',
|
||||
javassist: 'org.javassist:javassist:3.18.0-GA',
|
||||
|
||||
// Infinsipan
|
||||
infinispan: "org.infinispan:infinispan-core:${infinispanVersion}",
|
||||
|
|
|
@ -201,6 +201,17 @@ distributions {
|
|||
)
|
||||
}
|
||||
|
||||
into( 'lib/osgi' ) {
|
||||
from(
|
||||
( parent.project( 'hibernate-osgi' ).configurations.archives.allArtifacts.files.filter{ file -> !file.name.endsWith('-sources.jar') }
|
||||
+ parent.project( 'hibernate-osgi' ).configurations.runtime )
|
||||
- parent.project( 'hibernate-core' ).configurations.runtime
|
||||
- parent.project( 'hibernate-core' ).configurations.archives.allArtifacts.files
|
||||
- parent.project( 'hibernate-entitymanager' ).configurations.runtime
|
||||
- parent.project( 'hibernate-entitymanager' ).configurations.archives.allArtifacts.files
|
||||
)
|
||||
}
|
||||
|
||||
// todo : this closure is problematic as it does not write into the hibernate-release-$project.version directory
|
||||
// due to http://issues.gradle.org/browse/GRADLE-1450
|
||||
[ 'hibernate-c3p0', 'hibernate-proxool', 'hibernate-ehcache', 'hibernate-infinispan' ].each { feature ->
|
||||
|
|
Loading…
Reference in New Issue