【问题标题】:How to correctly externalise native SQL query with Spring Data JPA如何使用 Spring Data JPA 正确外部化本机 SQL 查询
【发布时间】:2021-01-06 11:06:29
【问题描述】:

我正试图摆脱我的 jpa-named-queries.properties,因为我觉得必须明确说明换行符很烦人。

因此,我想外部化我的原生 SQL 查询,但我无法做到,需要帮助。

GenericRecordRepository.java

public interface GenericRecordRepository extends JpaRepository<GenericRecord, Long> {

    ...

    @Query(nativeQuery = true)
    List<TransactionView> getTransactionListIncludingNull();

    ...

}

orm.xml

<named-query name="GenericRecord.getTransactionListIncludingNull">
    <query>
        SELECT ALL_DATES_CATEGORIES_MATRIX.CATEGORY, ALL_DATES_CATEGORIES_MATRIX.DATE, EXPENSES_BY_CATEGORY.AMOUNT
        FROM
        (
        -- Transaction list with expenses in € grouped by month and category
        SELECT CATEGORY, DATE_FORMAT(CAST(local_date as DATE), '%m-%Y') AS DATE, SUM(AMOUNT) AS AMOUNT
        FROM GENERIC_RECORD
        GROUP BY CATEGORY, DATE
        ) AS EXPENSES_BY_CATEGORY
        RIGHT JOIN
        (
        -- Categories and dates matrix
        SELECT *
        FROM
        (
        -- Dates where there was at least one expense
        SELECT DISTINCT DATE_FORMAT(CAST(local_date as DATE), '%m-%Y') AS DATE
        FROM GENERIC_RECORD
        ) AS DISTINCT_DATES
        CROSS JOIN
        (
        -- All categories
        SELECT DISTINCT CATEGORY
        FROM GENERIC_RECORD
        ) AS DISTINCT_CATEGORIES
        ) AS ALL_DATES_CATEGORIES_MATRIX
        ON
        EXPENSES_BY_CATEGORY.DATE = ALL_DATES_CATEGORIES_MATRIX.DATE AND
        EXPENSES_BY_CATEGORY.CATEGORY = ALL_DATES_CATEGORIES_MATRIX.CATEGORY
        ORDER BY CATEGORY, DATE ASC
    </query>
</named-query>

org.springframework.data.mapping.PropertyReferenceException: No property getTransactionListIncluding found for type GenericRecord! 时我收到此错误

我也尝试更改方法的名称,因为名称中的“Null”部分似乎被切断了,但没有任何区别

【问题讨论】:

    标签: java spring-data-jpa


    【解决方案1】:

    您应该修复一些时间:

    <?xml version="1.0" encoding="UTF-8"?>
    <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 http://xmlns.jcp.org/xml/ns/persistence/orm_2_1.xsd"
                     version="2.1">
                     ...
    </entity-mappings>
    
    • 检查查询类型:named-query标签用于HQL,named-native-query标签用于本地sql,第二个应提供result-class属性:

    例子:

    对于 HQL 查询:

    <?xml version="1.0" encoding="UTF-8"?>
    <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 http://xmlns.jcp.org/xml/ns/persistence/orm_2_1.xsd"
                     version="2.1">
        <named-query name="Customer.bauerUsers">
            <query>
                <![CDATA[
                select u from Customer u where u.lastName = 'Bauer'
                ]]>
            </query>
        </named-query>
    </entity-mappings>
    

    对于原生查询:

    <?xml version="1.0" encoding="UTF-8"?>
    <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 http://xmlns.jcp.org/xml/ns/persistence/orm_2_1.xsd"
                     version="2.1">
        <named-native-query name="Customer.bauerUsers" result-class="com.datajpa.entity.Customer">
            <query>
                <![CDATA[
                SELECT * FROM CUSTOMER WHERE LAST_NAME = 'Bauer'
                ]]>
            </query>
        </named-native-query>
    </entity-mappings>
    
    • repository方法的名字应该和orm.xml中的一样,@Query注解不是必须的:
    public interface CustomerRepository extends CrudRepository<Customer, Long> {
    
        List<Customer> bauerUsers();
    }
    

    您的工作版本应如下所示:


    public interface GenericRecordRepository extends JpaRepository<GenericRecord, Long> {
    
        List<TransactionView> getTransactionListIncludingNull();
    
    }
    

    文件orm.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <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 http://xmlns.jcp.org/xml/ns/persistence/orm_2_1.xsd"
                     version="2.1">
        <named-native-query name="GenericRecord.getTransactionListIncludingNull" result-class="<path_to_your_class>.TransactionView">
            <query>
                <![CDATA[
                SELECT ALL_DATES_CATEGORIES_MATRIX.CATEGORY, ALL_DATES_CATEGORIES_MATRIX.DATE, EXPENSES_BY_CATEGORY.AMOUNT
            FROM
            (
            -- Transaction list with expenses in € grouped by month and category
            SELECT CATEGORY, DATE_FORMAT(CAST(local_date as DATE), '%m-%Y') AS DATE, SUM(AMOUNT) AS AMOUNT
            FROM GENERIC_RECORD
            GROUP BY CATEGORY, DATE
            ) AS EXPENSES_BY_CATEGORY
            RIGHT JOIN
            (
            -- Categories and dates matrix
            SELECT *
            FROM
            (
            -- Dates where there was at least one expense
            SELECT DISTINCT DATE_FORMAT(CAST(local_date as DATE), '%m-%Y') AS DATE
            FROM GENERIC_RECORD
            ) AS DISTINCT_DATES
            CROSS JOIN
            (
            -- All categories
            SELECT DISTINCT CATEGORY
            FROM GENERIC_RECORD
            ) AS DISTINCT_CATEGORIES
            ) AS ALL_DATES_CATEGORIES_MATRIX
            ON
            EXPENSES_BY_CATEGORY.DATE = ALL_DATES_CATEGORIES_MATRIX.DATE AND
            EXPENSES_BY_CATEGORY.CATEGORY = ALL_DATES_CATEGORIES_MATRIX.CATEGORY
            ORDER BY CATEGORY, DATE ASC
                ]]>
            </query>
        </named-native-query>
    </entity-mappings>
    

    【讨论】:

      【解决方案2】:

      您没有在 JpaRepository 中使用标准 Spring Data 方法,例如 findById 或 deleteByName。 (在这些情况下,id 和 name 必须是 GenericRecord 类型中的属性。)

      在您的情况下,getTransactionListIncludingNull() 方法是您在 JpaRepository 中定义的自定义方法。要在 JpaRepository 中使用自定义方法,您应该定义一个新接口和它的实现。我想你没有考虑到这一点。

      有很多关于它的文章可以帮助你。 (例如。, https://www.baeldung.com/spring-data-jpa-method-in-all-repositories, Add Custom Method to JPARepository with Generics)

      【讨论】:

      • 感谢您的回答!但是,我认为您的回答与我的问题无关。问题是我想将一个大 SQL 移动到 orm.xml。我已经对我目前拥有的存储库感到满意。
      • 对不起,它没有帮助,但我所说的,可能会抛出这样的错误(PropertyReferenceException)。我试着根据你的错误来回答。
      猜你喜欢
      • 2019-12-01
      • 2019-03-01
      • 2019-03-22
      • 1970-01-01
      • 2019-06-21
      • 1970-01-01
      • 1970-01-01
      • 2019-04-15
      • 2018-09-23
      相关资源
      最近更新 更多