merge master
This commit is contained in:
commit
5d114797e1
|
@ -23,8 +23,13 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.dialect;
|
package org.hibernate.dialect;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
import java.sql.Types;
|
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.
|
* An SQL dialect for MySQL 5.x specific features.
|
||||||
*
|
*
|
||||||
|
@ -43,4 +48,27 @@ public class MySQL5Dialect extends MySQLDialect {
|
||||||
public boolean supportsColumnCheck() {
|
public boolean supportsColumnCheck() {
|
||||||
return false;
|
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 ( 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();
|
LOG.unregisteredStatement();
|
||||||
}
|
}
|
||||||
Set<ResultSet> resultSets = xref.get( statement );
|
Set<ResultSet> resultSets = xref.get( statement );
|
||||||
|
@ -448,7 +450,9 @@ public class JdbcCoordinatorImpl implements JdbcCoordinator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( statement != null ) {
|
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();
|
LOG.unregisteredStatement();
|
||||||
}
|
}
|
||||||
final Set<ResultSet> resultSets = xref.get( statement );
|
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.internal.util.StringHelper;
|
||||||
import org.hibernate.persister.collection.QueryableCollection;
|
import org.hibernate.persister.collection.QueryableCollection;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
|
import org.hibernate.persister.entity.Queryable;
|
||||||
import org.hibernate.sql.JoinFragment;
|
import org.hibernate.sql.JoinFragment;
|
||||||
import org.hibernate.sql.JoinType;
|
import org.hibernate.sql.JoinType;
|
||||||
import org.hibernate.type.CollectionType;
|
import org.hibernate.type.CollectionType;
|
||||||
|
@ -282,19 +283,36 @@ public class DotNode extends FromReferenceNode implements DisplayableNode, Selec
|
||||||
String propName = getPath();
|
String propName = getPath();
|
||||||
FromClause currentFromClause = getWalker().getCurrentFromClause();
|
FromClause currentFromClause = getWalker().getCurrentFromClause();
|
||||||
|
|
||||||
if ( getWalker().getStatementType() != SqlTokenTypes.SELECT && indexed && classAlias == null ) {
|
// determine whether we should use the table name or table alias to qualify the column names...
|
||||||
// should indicate that we are processing an INSERT/UPDATE/DELETE
|
// we need to use the table-name when:
|
||||||
// query with a subquery implied via a collection property
|
// 1) the top-level statement is not a SELECT
|
||||||
// function. Here, we need to use the table name itself as the
|
// 2) the LHS FromElement is *the* FromElement from the top-level statement
|
||||||
// qualification alias.
|
//
|
||||||
// TODO : verify this works for all databases...
|
// there is a caveat here.. if the update/delete statement are "multi-table" we should continue to use
|
||||||
// TODO : is this also the case in non-"indexed" scenarios?
|
// the alias also, even if the FromElement is the root one...
|
||||||
String alias = getLhs().getFromElement().getQueryable().getTableName();
|
//
|
||||||
columns = getFromElement().toColumns( alias, propertyPath, false, true );
|
// 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
|
// We do not look for an existing join on the same path, because
|
||||||
//it makes sense to join twice on the same collection role
|
// it makes sense to join twice on the same collection role
|
||||||
FromElementFactory factory = new FromElementFactory(
|
FromElementFactory factory = new FromElementFactory(
|
||||||
currentFromClause,
|
currentFromClause,
|
||||||
getLhs().getFromElement(),
|
getLhs().getFromElement(),
|
||||||
|
|
|
@ -27,6 +27,7 @@ import antlr.SemanticException;
|
||||||
import antlr.collections.AST;
|
import antlr.collections.AST;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import org.hibernate.hql.internal.antlr.HqlSqlTokenTypes;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -130,4 +131,15 @@ public abstract class FromReferenceNode extends AbstractSelectExpression
|
||||||
return null;
|
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() {
|
private boolean resolveAsAlias() {
|
||||||
// This is not actually a constant, but a reference to FROM element.
|
// This is not actually a constant, but a reference to FROM element.
|
||||||
FromElement element = getWalker().getCurrentFromClause().getFromElement( getText() );
|
final FromElement element = getWalker().getCurrentFromClause().getFromElement( getText() );
|
||||||
if ( element != null ) {
|
if ( element == null ) {
|
||||||
setType( SqlTokenTypes.ALIAS_REF );
|
return false;
|
||||||
setFromElement( element );
|
}
|
||||||
String[] columnExpressions = element.getIdentityColumns();
|
|
||||||
final boolean isInNonDistinctCount = getWalker().isInCount() && ! getWalker().isInCountDistinct();
|
setType( SqlTokenTypes.ALIAS_REF );
|
||||||
final boolean isCompositeValue = columnExpressions.length > 1;
|
setFromElement( element );
|
||||||
if ( isCompositeValue ) {
|
|
||||||
if ( isInNonDistinctCount && ! getWalker().getSessionFactoryHelper().getFactory().getDialect().supportsTupleCounts() ) {
|
String[] columnExpressions = element.getIdentityColumns();
|
||||||
setText( columnExpressions[0] );
|
|
||||||
}
|
// determine whether to apply qualification (table alias) to the column(s)...
|
||||||
else {
|
if ( ! isFromElementUpdateOrDeleteRoot( element ) ) {
|
||||||
String joinedFragment = StringHelper.join( ", ", columnExpressions );
|
if ( StringHelper.isNotEmpty( element.getTableAlias() ) ) {
|
||||||
// avoid wrapping in parenthesis (explicit tuple treatment) if possible due to varied support for
|
// apparently we also need to check that they are not already qualified. Ugh!
|
||||||
// tuple syntax across databases..
|
columnExpressions = StringHelper.qualifyIfNot( element.getTableAlias(), columnExpressions );
|
||||||
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 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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Type getNakedPropertyType(FromElement fromElement)
|
private Type getNakedPropertyType(FromElement fromElement) {
|
||||||
{
|
|
||||||
if (fromElement == null) {
|
if (fromElement == null) {
|
||||||
return 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)
|
@Message(value = "ResultSet had no statement associated with it, but was not yet registered", id = 386)
|
||||||
void unregisteredResultSetWithoutStatement();
|
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)
|
@Message(value = "ResultSet's statement was not registered", id = 387)
|
||||||
void unregisteredStatement();
|
void unregisteredStatement();
|
||||||
|
|
||||||
|
|
|
@ -465,7 +465,9 @@ public final class StringHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String[] qualify(String prefix, String[] names) {
|
public static String[] qualify(String prefix, String[] names) {
|
||||||
if ( prefix == null ) return names;
|
if ( prefix == null ) {
|
||||||
|
return names;
|
||||||
|
}
|
||||||
int len = names.length;
|
int len = names.length;
|
||||||
String[] qualified = new String[len];
|
String[] qualified = new String[len];
|
||||||
for ( int i = 0; i < len; i++ ) {
|
for ( int i = 0; i < len; i++ ) {
|
||||||
|
@ -473,6 +475,24 @@ public final class StringHelper {
|
||||||
}
|
}
|
||||||
return qualified;
|
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) {
|
public static int firstIndexOfChar(String sqlString, BitSet keys, int startindex) {
|
||||||
for ( int i = startindex, size = sqlString.length(); i < size; i++ ) {
|
for ( int i = startindex, size = sqlString.length(); i < size; i++ ) {
|
||||||
if ( keys.get( sqlString.charAt( i ) ) ) {
|
if ( keys.get( sqlString.charAt( i ) ) ) {
|
||||||
|
|
|
@ -205,6 +205,16 @@ public abstract class AbstractEntityJoinWalker extends JoinWalker {
|
||||||
public final String getAlias() {
|
public final String getAlias() {
|
||||||
return alias;
|
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() {
|
public String toString() {
|
||||||
return getClass().getName() + '(' + getPersister().getEntityName() + ')';
|
return getClass().getName() + '(' + getPersister().getEntityName() + ')';
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.annotations.id;
|
package org.hibernate.test.annotations.id;
|
||||||
|
|
||||||
|
import org.hibernate.test.annotations.id.entities.Hotel;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.hibernate.Session;
|
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.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Emmanuel Bernard
|
* @author Emmanuel Bernard
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public class IdTest extends BaseCoreFunctionalTestCase {
|
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
|
@Test
|
||||||
public void testGenericGenerator() throws Exception {
|
public void testGenericGenerator() throws Exception {
|
||||||
Session s = openSession();
|
Session s = openSession();
|
||||||
|
@ -319,7 +359,7 @@ public class IdTest extends BaseCoreFunctionalTestCase {
|
||||||
Department.class, Dog.class, Computer.class, Home.class,
|
Department.class, Dog.class, Computer.class, Home.class,
|
||||||
Phone.class, Tree.class, FirTree.class, Footballer.class,
|
Phone.class, Tree.class, FirTree.class, Footballer.class,
|
||||||
SoundSystem.class, Furniture.class, GoalKeeper.class,
|
SoundSystem.class, Furniture.class, GoalKeeper.class,
|
||||||
BreakDance.class, Monkey.class};
|
BreakDance.class, Monkey.class, Hotel.class };
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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.FailureExpected;
|
||||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||||
import org.hibernate.testing.SkipForDialect;
|
import org.hibernate.testing.SkipForDialect;
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -472,7 +473,11 @@ public class QueryAndSQLTest extends BaseCoreFunctionalTestCase {
|
||||||
Chaos.class,
|
Chaos.class,
|
||||||
CasimirParticle.class,
|
CasimirParticle.class,
|
||||||
AllTables.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',
|
dom4j: 'dom4j:dom4j:1.6.1@jar',
|
||||||
|
|
||||||
// Javassist
|
// Javassist
|
||||||
javassist: 'org.javassist:javassist:3.15.0-GA',
|
javassist: 'org.javassist:javassist:3.18.0-GA',
|
||||||
|
|
||||||
// Infinsipan
|
// Infinsipan
|
||||||
infinispan: "org.infinispan:infinispan-core:${infinispanVersion}",
|
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
|
// 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
|
// due to http://issues.gradle.org/browse/GRADLE-1450
|
||||||
[ 'hibernate-c3p0', 'hibernate-proxool', 'hibernate-ehcache', 'hibernate-infinispan' ].each { feature ->
|
[ 'hibernate-c3p0', 'hibernate-proxool', 'hibernate-ehcache', 'hibernate-infinispan' ].each { feature ->
|
||||||
|
|
Loading…
Reference in New Issue