• 如何在@GenericGenerator中显式指定schema


    现在的情况是,在MySQL中有db1和db2两个数据库。项目使用Hibernate,可同时访问db1和db2,默认数据库为db1。表table2在db2中。且table2的主键名为ids,是自增长字段(Auto Increment)。

    table2和ids的定义为:

    1. @Entity
    2. @Table(name = "table2", schema = "db2")
    3. @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
    4. public class Table2 implements java.io.Serializable {
    5. private static final long serialVersionUID = 48L;
    6. @Id
    7. @Column(name = "ids")
    8. @GeneratedValue(generator = "idGenerator", strategy = GenerationType.IDENTITY)
    9. @GenericGenerator(name = "idGenerator", strategy = "increment")
    10. private Integer ids;

    当向table2中保存数据时,会报错。原因是生成ids时,系统会查询table2中ids的最大值。语句是:

    select max(ids) from table2

    由于默认数据库是db1,因此查询的是db1.table2表。但table2表实际上在db2中,所以系统找不到该表,从而报错。

    这就需要在@GenericGenerator中指定max查询语句的schema。通过检查错误信息,发现对应代码在org.hibernate.id.IncrementGenerator.configure()方法中,如下:

    1. public void configure(Type type, Properties params, Dialect dialect) throws MappingException {
    2. returnClass = type.getReturnedClass();
    3. ObjectNameNormalizer normalizer =
    4. ( ObjectNameNormalizer ) params.get( PersistentIdentifierGenerator.IDENTIFIER_NORMALIZER );
    5. String column = params.getProperty( "column" );
    6. if ( column == null ) {
    7. column = params.getProperty( PersistentIdentifierGenerator.PK );
    8. }
    9. column = dialect.quote( normalizer.normalizeIdentifierQuoting( column ) );
    10. String tableList = params.getProperty( "tables" );
    11. if ( tableList == null ) {
    12. tableList = params.getProperty( PersistentIdentifierGenerator.TABLES );
    13. }
    14. String[] tables = StringHelper.split( ", ", tableList );
    15. final String schema = dialect.quote(
    16. normalizer.normalizeIdentifierQuoting(
    17. params.getProperty( PersistentIdentifierGenerator.SCHEMA )
    18. )
    19. );
    20. final String catalog = dialect.quote(
    21. normalizer.normalizeIdentifierQuoting(
    22. params.getProperty( PersistentIdentifierGenerator.CATALOG )
    23. )
    24. );
    25. StringBuilder buf = new StringBuilder();
    26. for ( int i=0; i < tables.length; i++ ) {
    27. final String tableName = dialect.quote( normalizer.normalizeIdentifierQuoting( tables[i] ) );
    28. if ( tables.length > 1 ) {
    29. buf.append( "select max(" ).append( column ).append( ") as mx from " );
    30. }
    31. buf.append( Table.qualify( catalog, schema, tableName ) );
    32. if ( i < tables.length-1 ) {
    33. buf.append( " union " );
    34. }
    35. }
    36. if ( tables.length > 1 ) {
    37. buf.insert( 0, "( " ).append( " ) ids_" );
    38. column = "ids_.mx";
    39. }
    40. sql = "select max(" + column + ") from " + buf.toString();
    41. }

    在初始化Table2实体类时,该方法就会执行。作用是生成对应数据库的select max语句。

    在IncrementGenerator的注释中,有一段话:

    Mapping parameters supported, but not usually needed: tables, column. (The tables parameter specified a comma-separated list of table names.)

    说明在@GenericGenerator中,可以设置参数。在IncrementGenerator.configure()方法中,可以将这些参数读出来。读取参数的方法为params.getProperty("参数名")。例如:

    params.getProperty( "column" )

    就是读取column参数的值。对应读取schema的语句为:

    1. final String schema = dialect.quote(
    2. normalizer.normalizeIdentifierQuoting(
    3. params.getProperty( PersistentIdentifierGenerator.SCHEMA )
    4. )
    5. );

    schema的参数名就是PersistentIdentifierGenerator.SCHEMA,也就是"schema"。其他预置保留参数的值大都在org.hibernate.id.PersistentIdentifierGenerator中定义。如:

    1. public interface PersistentIdentifierGenerator extends IdentifierGenerator {
    2. /**
    3. * The configuration parameter holding the schema name
    4. */
    5. public static final String SCHEMA = "schema";
    6. /**
    7. * The configuration parameter holding the table name for the
    8. * generated id
    9. */
    10. public static final String TABLE = "target_table";
    11. /**
    12. * The configuration parameter holding the table names for all
    13. * tables for which the id must be unique
    14. */
    15. public static final String TABLES = "identity_tables";
    16. /**
    17. * The configuration parameter holding the primary key column
    18. * name of the generated id
    19. */
    20. public static final String PK = "target_column";
    21. /**
    22. * The configuration parameter holding the catalog name
    23. */
    24. public static final String CATALOG = "catalog";
    25. /**
    26. * The key under whcih to find the {@link org.hibernate.cfg.ObjectNameNormalizer} in the config param map.
    27. */
    28. public static final String IDENTIFIER_NORMALIZER = "identifier_normalizer";

    在@GenericGenerator中设置parameter的方法为:

    1. @Id
    2. @Column(name = "ids")
    3. @GeneratedValue(generator = "idGenerator", strategy = GenerationType.IDENTITY)
    4. @GenericGenerator(name = "idGenerator", strategy = "increment", parameters = @Parameter(name = PersistentIdentifierGenerator.SCHEMA, value = "db2"))
    5. private Integer ids;

    这样就能在table2前加上正确的schema名称(db2),生成正确的查询语句:

    select max(ids) from db2.table2

    如果有多个参数,可以写为:

    @GenericGenerator(name = "idGenerator", strategy = "increment", parameters = {
                @Parameter(name = PersistentIdentifierGenerator.SCHEMA, value = "db2"),
                @Parameter(name=PersistentIdentifierGenerator.CATALOG, value = "db2")

    })

  • 相关阅读:
    看着2022年世界杯,我无比怀念98世界杯
    前端周刊第三十八期
    Haproxy搭建Web集群
    vue 3 + TS 组合式标注类型
    网络协议:透彻解析HTTP协议
    算法通关村第九关-白银挑战二分查找与高频搜索树
    TOR(Top of Rack)
    产生自卑心理的原因是什么?
    (Qt+Vs编译环境)报错:引发异常,写入访问权限冲突
    hdfs读流程
  • 原文地址:https://blog.csdn.net/spy2000/article/details/142211847