【问题标题】:Hibernate @Formula doesn't include SchemaHibernate @Formula 不包含架构
【发布时间】:2018-12-07 20:09:41
【问题描述】:

我有一个具有 @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 正在被读取并包含在表中,但未包含在函数中,

是否有一个选项/注释可以在该函数中强制使用 shema?

我尝试过休眠 5.1 和 5.2,结果相同 :(

【问题讨论】:

  • 你在这里指的是什么功能?
  • AFAIK,@Formula.value 的内容逐字传递给查询。为RUTAAREA 创建一个全局别名(但不确定SQLServer 是否支持这种别名)或在RUTAAREA 前面加上架构名称
  • @crizzis 我无法在代码中添加架构,因为它可以更改我无法为每种情况构建自定义部署,我不确定,但可以为表而不是函数创建别名: (
  • @crizzis 我为该函数添加了一个别名到 dbo 但它是相同的,查询结束如下: select dbo.RUTAAREA(idarea) from sigap.areasAuxiliar;没有“dbo”就无法识别。
  • 我想这就是你要找的东西:stackoverflow.com/questions/43635745/…

标签: java sql-server hibernate jpa hql


【解决方案1】:

更简化的解决方案:

从此更改您的@Formula:

@Formula("RUTAAREA(idArea)")

到这里:

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

创建一个类:

public class HibernateEntityInterceptor extends EmptyInterceptor {

}

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

sessionFactory.setEntityInterceptor(new HibernateEntityInterceptor());

然后在那个类中你重写这个方法:

public String onPrepareStatement(String sql) {

该方法在执行之前接收 sql 命令,因此,您只需简单地全部替换即可:

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

感谢您的帮助。

【讨论】:

  • @Dan 不要误会我的意思,这几乎是你的答案,但我试图让它更清楚,并且只替换模式的关键字,而不是模式+函数,所以这可以也可以使用 NamedNativeQuery
【解决方案2】:

不确定这是否有助于应用于函数,但您是否尝试将属性“模式”添加到 @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;

然后添加一个拦截器来填充公式的值。解决方案的链接是Hibernate @Formula set value at runtime

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

【讨论】:

    【解决方案3】:

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

    "SELECT x FROM {h-schema}tableName"
    

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

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

    【讨论】:

    • 您是否尝试过第二种解决方法(有替换)?
    【解决方案4】:

    您可以使用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>
    

    注意:大量灵感来自 How to change Hibernate GenerationType identifier depending on the underlying database

    注(2):在blog posthere中,作者在运行时生成PersistenceUnitInfo。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-03
      • 2014-09-28
      相关资源
      最近更新 更多