HHH-16638 allow @DialectOverride for @SQLInsert and friends
This commit is contained in:
parent
62c05eadb9
commit
47d8a63f16
|
@ -380,12 +380,108 @@ public interface DialectOverride {
|
|||
|
||||
org.hibernate.annotations.SQLSelect override();
|
||||
}
|
||||
@Target({METHOD, FIELD})
|
||||
@Target({METHOD, FIELD, TYPE})
|
||||
@Retention(RUNTIME)
|
||||
@interface SQLSelects {
|
||||
SQLSelect[] value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Specializes a {@link org.hibernate.annotations.SQLInsert}
|
||||
* in a certain dialect.
|
||||
*/
|
||||
@Target({METHOD, FIELD, TYPE})
|
||||
@Retention(RUNTIME)
|
||||
@Repeatable(SQLInserts.class)
|
||||
@OverridesAnnotation(org.hibernate.annotations.SQLInsert.class)
|
||||
@interface SQLInsert {
|
||||
/**
|
||||
* The {@link Dialect} in which this override applies.
|
||||
*/
|
||||
Class<? extends Dialect> dialect();
|
||||
Version before() default @Version(major = MAX_VALUE);
|
||||
Version sameOrAfter() default @Version(major = MIN_VALUE);
|
||||
|
||||
org.hibernate.annotations.SQLInsert override();
|
||||
}
|
||||
@Target({METHOD, FIELD, TYPE})
|
||||
@Retention(RUNTIME)
|
||||
@interface SQLInserts {
|
||||
SQLInsert[] value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Specializes a {@link org.hibernate.annotations.SQLUpdate}
|
||||
* in a certain dialect.
|
||||
*/
|
||||
@Target({METHOD, FIELD, TYPE})
|
||||
@Retention(RUNTIME)
|
||||
@Repeatable(SQLUpdates.class)
|
||||
@OverridesAnnotation(org.hibernate.annotations.SQLUpdate.class)
|
||||
@interface SQLUpdate {
|
||||
/**
|
||||
* The {@link Dialect} in which this override applies.
|
||||
*/
|
||||
Class<? extends Dialect> dialect();
|
||||
Version before() default @Version(major = MAX_VALUE);
|
||||
Version sameOrAfter() default @Version(major = MIN_VALUE);
|
||||
|
||||
org.hibernate.annotations.SQLUpdate override();
|
||||
}
|
||||
@Target({METHOD, FIELD, TYPE})
|
||||
@Retention(RUNTIME)
|
||||
@interface SQLUpdates {
|
||||
SQLUpdate[] value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Specializes a {@link org.hibernate.annotations.SQLDelete}
|
||||
* in a certain dialect.
|
||||
*/
|
||||
@Target({METHOD, FIELD, TYPE})
|
||||
@Retention(RUNTIME)
|
||||
@Repeatable(SQLDeletes.class)
|
||||
@OverridesAnnotation(org.hibernate.annotations.SQLDelete.class)
|
||||
@interface SQLDelete {
|
||||
/**
|
||||
* The {@link Dialect} in which this override applies.
|
||||
*/
|
||||
Class<? extends Dialect> dialect();
|
||||
Version before() default @Version(major = MAX_VALUE);
|
||||
Version sameOrAfter() default @Version(major = MIN_VALUE);
|
||||
|
||||
org.hibernate.annotations.SQLDelete override();
|
||||
}
|
||||
@Target({METHOD, FIELD, TYPE})
|
||||
@Retention(RUNTIME)
|
||||
@interface SQLDeletes {
|
||||
SQLDelete[] value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Specializes a {@link org.hibernate.annotations.SQLDeleteAll}
|
||||
* in a certain dialect.
|
||||
*/
|
||||
@Target({METHOD, FIELD, TYPE})
|
||||
@Retention(RUNTIME)
|
||||
@Repeatable(SQLDeleteAlls.class)
|
||||
@OverridesAnnotation(org.hibernate.annotations.SQLDeleteAll.class)
|
||||
@interface SQLDeleteAll {
|
||||
/**
|
||||
* The {@link Dialect} in which this override applies.
|
||||
*/
|
||||
Class<? extends Dialect> dialect();
|
||||
Version before() default @Version(major = MAX_VALUE);
|
||||
Version sameOrAfter() default @Version(major = MIN_VALUE);
|
||||
|
||||
org.hibernate.annotations.SQLDeleteAll override();
|
||||
}
|
||||
@Target({METHOD, FIELD, TYPE})
|
||||
@Retention(RUNTIME)
|
||||
@interface SQLDeleteAlls {
|
||||
SQLDeleteAll[] value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks an annotation type as a dialect-specific override for
|
||||
* some other annotation type.
|
||||
|
|
|
@ -1252,8 +1252,6 @@ public class EntityBinder {
|
|||
|
||||
private void bindCustomSql() {
|
||||
//TODO: tolerate non-empty table() member here if it explicitly names the main table
|
||||
//TODO: would be nice to add these guys to @DialectOverride, but getOverridableAnnotation()
|
||||
// does not yet handle repeatable annotations
|
||||
|
||||
final SQLInsert sqlInsert = findMatchingSqlAnnotation( "", SQLInsert.class, SQLInserts.class );
|
||||
if ( sqlInsert != null ) {
|
||||
|
@ -1950,12 +1948,13 @@ public class EntityBinder {
|
|||
String tableName,
|
||||
Class<T> annotationType,
|
||||
Class<R> repeatableType) {
|
||||
final T sqlAnnotation = annotatedClass.getAnnotation( annotationType );
|
||||
final T sqlAnnotation = getOverridableAnnotation( annotatedClass, annotationType, context );
|
||||
if ( sqlAnnotation != null ) {
|
||||
if ( tableName.equals( tableMember( annotationType, sqlAnnotation ) ) ) {
|
||||
return sqlAnnotation;
|
||||
}
|
||||
}
|
||||
//TODO: getOverridableAnnotation() does not yet handle @Repeatable annotations
|
||||
final R repeatable = annotatedClass.getAnnotation(repeatableType);
|
||||
if ( repeatable != null ) {
|
||||
for ( Annotation current : valueMember( repeatableType, repeatable ) ) {
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
package org.hibernate.orm.test.customsql;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import org.hibernate.annotations.DialectOverride;
|
||||
import org.hibernate.annotations.Generated;
|
||||
import org.hibernate.annotations.SQLInsert;
|
||||
import org.hibernate.annotations.SQLUpdate;
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
import org.hibernate.dialect.MySQLDialect;
|
||||
import org.hibernate.dialect.PostgreSQLDialect;
|
||||
import org.hibernate.dialect.SQLServerDialect;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.RequiresDialect;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
@SessionFactory
|
||||
@DomainModel(annotatedClasses = CustomSqlOverrideTest.Custom.class)
|
||||
@RequiresDialect(H2Dialect.class)
|
||||
@RequiresDialect(MySQLDialect.class)
|
||||
@RequiresDialect(PostgreSQLDialect.class)
|
||||
@RequiresDialect(SQLServerDialect.class)
|
||||
public class CustomSqlOverrideTest {
|
||||
@Test
|
||||
public void testCustomSql(SessionFactoryScope scope) {
|
||||
Custom c = new Custom();
|
||||
scope.inTransaction(s->{
|
||||
s.persist(c);
|
||||
c.whatever = "old value";
|
||||
s.flush();
|
||||
assertNotNull(c.id);
|
||||
assertNotNull(c.uid);
|
||||
s.clear();
|
||||
Custom cc = s.find(Custom.class, c.id);
|
||||
assertNotNull(cc.id);
|
||||
assertNotNull(cc.uid);
|
||||
assertEquals("old value", cc.whatever);
|
||||
cc.whatever = "new value";
|
||||
s.flush();
|
||||
s.clear();
|
||||
Custom ccc = s.find(Custom.class, c.id);
|
||||
assertNotNull(cc.id);
|
||||
assertNotNull(cc.uid);
|
||||
assertEquals("new value", ccc.whatever);
|
||||
assertEquals(cc.id, ccc.id);
|
||||
assertNotEquals(cc.uid, ccc.uid);
|
||||
});
|
||||
}
|
||||
@Entity
|
||||
@Table(name = "CustomTable")
|
||||
// @SQLInsert(sql="")
|
||||
@DialectOverride.SQLInsert(dialect = H2Dialect.class,
|
||||
override = @SQLInsert(sql="insert into CustomTable (uid,whatever) values (random_uuid(),?)"))
|
||||
@DialectOverride.SQLInsert(dialect = MySQLDialect.class,
|
||||
override = @SQLInsert(sql="insert into CustomTable (uid,whatever) values (uuid(),?)"))
|
||||
@DialectOverride.SQLInsert(dialect = PostgreSQLDialect.class,
|
||||
override = @SQLInsert(sql="insert into CustomTable (uid,whatever) values (gen_random_uuid(),?)"))
|
||||
@DialectOverride.SQLInsert(dialect = SQLServerDialect.class,
|
||||
override = @SQLInsert(sql="insert into CustomTable (uid,whatever) values (newid(),?)"))
|
||||
// @SQLUpdate(sql="")
|
||||
@DialectOverride.SQLUpdate(dialect = H2Dialect.class,
|
||||
override = @SQLUpdate(sql="update CustomTable set uid = random_uuid(), whatever = ? where id = ?"))
|
||||
@DialectOverride.SQLUpdate(dialect = MySQLDialect.class,
|
||||
override = @SQLUpdate(sql="update CustomTable set uid = uuid(), whatever = ? where id = ?"))
|
||||
@DialectOverride.SQLUpdate(dialect = PostgreSQLDialect.class,
|
||||
override = @SQLUpdate(sql="update CustomTable set uid = gen_random_uuid(), whatever = ? where id = ?"))
|
||||
@DialectOverride.SQLUpdate(dialect = SQLServerDialect.class,
|
||||
override = @SQLUpdate(sql="update CustomTable set uid = newid(), whatever = ? where id = ?"))
|
||||
static class Custom {
|
||||
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
Long id;
|
||||
@Generated
|
||||
String uid;
|
||||
String whatever;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue