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();
|
org.hibernate.annotations.SQLSelect override();
|
||||||
}
|
}
|
||||||
@Target({METHOD, FIELD})
|
@Target({METHOD, FIELD, TYPE})
|
||||||
@Retention(RUNTIME)
|
@Retention(RUNTIME)
|
||||||
@interface SQLSelects {
|
@interface SQLSelects {
|
||||||
SQLSelect[] value();
|
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
|
* Marks an annotation type as a dialect-specific override for
|
||||||
* some other annotation type.
|
* some other annotation type.
|
||||||
|
|
|
@ -1252,8 +1252,6 @@ public class EntityBinder {
|
||||||
|
|
||||||
private void bindCustomSql() {
|
private void bindCustomSql() {
|
||||||
//TODO: tolerate non-empty table() member here if it explicitly names the main table
|
//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 );
|
final SQLInsert sqlInsert = findMatchingSqlAnnotation( "", SQLInsert.class, SQLInserts.class );
|
||||||
if ( sqlInsert != null ) {
|
if ( sqlInsert != null ) {
|
||||||
|
@ -1950,12 +1948,13 @@ public class EntityBinder {
|
||||||
String tableName,
|
String tableName,
|
||||||
Class<T> annotationType,
|
Class<T> annotationType,
|
||||||
Class<R> repeatableType) {
|
Class<R> repeatableType) {
|
||||||
final T sqlAnnotation = annotatedClass.getAnnotation( annotationType );
|
final T sqlAnnotation = getOverridableAnnotation( annotatedClass, annotationType, context );
|
||||||
if ( sqlAnnotation != null ) {
|
if ( sqlAnnotation != null ) {
|
||||||
if ( tableName.equals( tableMember( annotationType, sqlAnnotation ) ) ) {
|
if ( tableName.equals( tableMember( annotationType, sqlAnnotation ) ) ) {
|
||||||
return sqlAnnotation;
|
return sqlAnnotation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//TODO: getOverridableAnnotation() does not yet handle @Repeatable annotations
|
||||||
final R repeatable = annotatedClass.getAnnotation(repeatableType);
|
final R repeatable = annotatedClass.getAnnotation(repeatableType);
|
||||||
if ( repeatable != null ) {
|
if ( repeatable != null ) {
|
||||||
for ( Annotation current : valueMember( repeatableType, repeatable ) ) {
|
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