Hibernate @Formula不包含架构

时间:2018-06-28 16:54:13

标签: java sql-server hibernate jpa hql

我有一个具有属性 @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,结果相同:(

4 个答案:

答案 0 :(得分: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。

答案 1 :(得分:2)

不确定这是否对函数有用,但是您是否尝试过将属性'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;

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

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

答案 2 :(得分:0)

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

"SELECT x FROM {h-schema}tableName"

试一试,看看是否偶然也可以在@Formula中工作...

2)如果不是,您也可以尝试使用替代项(例如hibernate.query.substitutions),以告诉hibernate用S'替换文字S-在您的情况下,“ RUTAAREA”为“ schema.RUTAAREA”?

答案 3 :(得分:-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;

感谢帮助。