Hibernate @Formula 不包含 Schema

Hibernate @Formula doesn't include Schema

我有一个带有 属性 @Formula 的实体,如下所示:

@Entity
@Table(name = "areasAuxiliar")
public final class AreaAuxiliar implements Serializable {

    @Id
    @Column(name = "idArea")
    private Integer idArea;

    @Formula("RUTAAREA(idArea)")
    private String ruta;

当我将我的休眠配置为指向 Oracle 数据库时我没有问题, 但是,当我切换到 SQLServer 时,休眠不包括 shema 并且查询失败,

为休眠生成的查询如下所示:

select
    areaauxili4_.idArea as idArea1_6_4_,
    rutaArea(areaauxili4_.idArea) as formula2_4_
from
    SIGAP.areasAuxiliar areaauxili4_ 

正在读取参数 hibernate.default_schema=SIGAP 并包含在 table 中,但不在函数中,

是否有 option/annotation 强制 shema 进入该功能?

我试过 hibernate 5.1 和 5.2,结果相同 :(

您可以使用 mysql-orm.xml 文件来覆盖您的公式,然后将您的构建配置为在数据库为 mysql.

时考虑该文件

在这里重写公式:

<entity-mappings
    xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm orm_2_1.xsd"
    version="2.1">
    <package>com.acme.persistence</package>
    <entity class="AreaAuxiliar" access="FIELD">
        <attributes>
            <property name="ruta" formula="schemaName.RUTAAREA(idarea)"/>
        </attributes>
    </entity>
</entity-mappings>

然后在特定的persistence.xml中添加引用。然后,您可以在您的构建中或在 运行 时间(参见下面的链接)用这个覆盖默认值 persistence.xml。

<persistence
xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">

<persistence-unit name="persistenceUnit">

    <provider>
        org.hibernate.jpa.HibernatePersistenceProvider
    </provider>

    <mapping-file>
        mappings/identifier/global/mysql-orm.xml
    </mapping-file>

    <class>
        com.acme.persistence.AreaAuxiliar 
    </class>

</persistence-unit>

注:深受启发

注(2):在blog post and here,作者在运行时生成了PersistenceUnitInfo。

1) 我知道对于 native 查询,您可以使用“{h-schema}”占位符(它将填充 "hibernate.default_schema" 的值参数):

"SELECT x FROM {h-schema}tableName"

试试看这是否也适用于@Formula...

2) 如果不是,您也可以尝试使用替换(即 hibernate.query.substitutions)来告诉休眠将文字 S 替换为 S' - 在您的情况下 "RUTAAREA" 为 "schema.RUTAAREA" ?

不确定这是否有助于应用于函数,但您是否尝试过将 属性 'schema' 添加到 @Table 注释中:

@Entity
@Table(name = "areasAuxiliar", schema="mySchemaName")
public final class AreaAuxiliar implements Serializable {

    @Id
    @Column(name = "idArea")
    private Integer idArea;

    @Formula("RUTAAREA(idArea)")
    private String ruta;

另一种解决方案,转为注释,在@Formula注解中使用占位符

@Entity
@Table(name = "areasAuxiliar")
public final class AreaAuxiliar implements Serializable {

    @Id
    @Column(name = "idArea")
    private Integer idArea;

    @Formula("{SCHEMA_AND_FUNCTION}")
    private String ruta;

然后添加一个拦截器来填充公式的值。解决方案的 link 是

最后,请参阅我关于在 SQLSERVER 中创建全局函数的评论。可以在这里找到详细信息 Can I create create a global function in SQL Server?

更简单的解决方案:

改变你的@Formula:

@Formula("RUTAAREA(idArea)")

对此:

@Formula("{MYAPP_SCHEMA}.RUTAAREA(idArea)")

创建 class:

public class HibernateEntityInterceptor extends EmptyInterceptor {

}

在您的 sessionFactory 中将其注册为实体拦截器,在我的例子中:

sessionFactory.setEntityInterceptor(new HibernateEntityInterceptor());

然后在 class 中重写此方法:

public String onPrepareStatement(String sql) {

该方法在执行之前收到 sql 命令,因此,您需要做的就是简单地全部替换:

sql = sql.replaceAll("\{MYAPP_SCHEMA}", default_schema);
return sql;

感谢您的帮助。