【问题标题】:ERROR: operator does not exist: character varying = bytea错误:运算符不存在:字符变化 = bytea
【发布时间】:2012-05-19 18:06:02
【问题描述】:

我在 postgres 中有一个表,结构如下

CREATE TABLE rpaul."HK_LOGIN_DETAILS"
(
  "HK_LOGIN_DETAILS_ID" bigint NOT NULL,
  "HK_LOGIN_DETAILS_USERNAME" character varying(10) NOT NULL,
  "HK_LOGIN_DETAILS_PASSWORD" character varying(50) NOT NULL,
  CONSTRAINT "HK_LOGIN_DETAILS_PK" PRIMARY KEY ("HK_LOGIN_DETAILS_ID" ),
  CONSTRAINT "HK_LOGIN_DETAILS_UK" UNIQUE ("HK_LOGIN_DETAILS_USERNAME" )
)

这个表的hibernate映射如下所述

<hibernate-mapping package="net.rpaul.projects.homekeeping.domain.login">
    <class name="LoginDetails" table="`HK_LOGIN_DETAILS`">
        <id name="id" column="`HK_LOGIN_DETAILS_ID`" type="long">
            <generator class="assigned" />
        </id>
        <property name="userName" type="string" column="`HK_LOGIN_DETAILS_USERNAME`" not-null="true" />
        <property name="password" type="string" column="`HK_LOGIN_DETAILS_PASSWORD`" not-null="true" />
    </class>
</hibernate-mapping>

在 LoginDetails.java 中,我将 id 字段声明为 long,将 userName 和 password 字段声明为 String。仍然当我尝试执行以下

List list =  getHibernateTemplate().find("from LoginDetails ld where ld.userName = ?", userName);

我明白了

错误:运算符不存在:字符变化 = bytea

我不明白出了什么问题。任何帮助将不胜感激。

【问题讨论】:

    标签: hibernate postgresql


    【解决方案1】:

    故障排除清单:

    #1 : 根据您使用的数据库类型,您可能希望找到该列 使用此 SQL 命令的名称及其各自的数据类型:

    SELECT
       table_name,
       column_name,
       data_type
    FROM
       information_schema.columns
    WHERE
       table_name = 'the-name-of-the-table-in-the-database';
    

    预期结果将为您提供三列;尤其是“data_type”列。

    确保您的 Pojo 类和相应的数据类型正确匹配。

    注意:数据库里面的表中的bigint(数据类型)可以与Long无缝匹配。 带 int 的整数。字符随 String 或主要的 java 类而变化,例如。一个存储枚举的类,等等。

    确认上述后,进行下一步检查 -> 故障排除:

    #2:此故障排除的主要检查是检查所有数据类型是否匹配 完美。请注意传递给查询的参数。

    传递一个枚举 or 或任何其他数据类型或不符合 SQL 数据类型的枚举类型 即使 pojo 类与 数据库中的表结构。

    pojo 示例:UserAccountBalance.class

    import io.swagger.v3.oas.annotations.media.Schema;
    import lombok.*;
    
    @Builder//Lombok
    @AllArgsConstructor(access = AccessLevel.PRIVATE)
    @NoArgsConstructor(access = AccessLevel.PUBLIC)
    @Data//Lombok
    @EqualsAndHashCode(callSuper = true)
    @ToString(callSuper = true)
    @Schema
    @Entity(name = "user_account_balance")
    @Table(name = "user_account_balance")
    public class UserAccountBalance {
    
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        @Column(name = "id")
        private long id;
    
        @NotNull
        @Column(name = "username", nullable = false)
        private String userName;
    
        @NotNull
        @Column(name="currency_code", nullable = false)
        @Enumerated(EnumType.STRING)
        private CurrencyCode currencyCode;
    
        @NotNull
        @Column(name = "balance", nullable = false)
        private BigDecimal balance;
    
    //Could be placed into and AuditModel class
        @Column(name = "datecreated", nullable = false, updatable = false)
        @JsonIgnore
        @DateCreated
        @CreationTimestamp
        private LocalDateTime dateCreated;
    
        @Column(name = "date_updated", nullable = false, updatable = false)
        @JsonIgnore
        @DateUpdated
        private LocalDateTime dateUpdated;
    
        @NotNull
        @Column(name = "active")
        @JsonIgnore
        private int active;
    
        @Column(name = "deleted")
        @JsonIgnore
        private int deleted;
    
    }
    

    存储库类:

    //选项1:UserAccountBalanceRepository.class

    @Repository
    public abstract class UserAccountBalanceRepository implements CrudRepository<UserAccountBalance, Long> {
    
        private final EntityManager entityManager;
    
        public UserAccountBalanceRepository(@CurrentSession EntityManager entityManager){
            this.entityManager = entityManager;
        }
    
        @Transactional(readOnly = true)
        @Query(
                value="SELECT uab.*" +
                        " FROM public.user_account_balance uab" +
                        " WHERE (currency_code =cast(:currencyCode AS text)" +
                        " AND userName =:userName" +
                        " AND active =:active)",
                countQuery = "SELECT uab.*" +
                        " FROM public.user_account_balance uab" +
                        " WHERE (currency_code = cast(:currencyCode AS text)" +
                        " AND userName =:userName" +
                        " AND active =:active)",
                nativeQuery = true
        )
        public abstract Optional<UserAccountBalance> findByUserAccountBalance_UserName_And_CurrencyCode(
                String userName,
                CurrencyCode currencyCode,
                int active
        );
    
    }
    

    //选项2:UserAccountBalanceRepository.class

    @Repository
    public abstract class UserAccountBalanceRepository implements CrudRepository<UserAccountBalance, Long> {
    
        private final EntityManager entityManager;
    
        public UserAccountBalanceRepository(@CurrentSession EntityManager entityManager){
            this.entityManager = entityManager;
        }
    
        @Transactional(readOnly = true)
        @Query(
                value="SELECT uab.*" +
                        " FROM public.user_account_balance uab" +
                        " WHERE (currency_code =:currencyCode" +
                        " AND userName =:userName" +
                        " AND active =:active)",
                countQuery = "SELECT uab.*" +
                        " FROM public.user_account_balance uab" +
                        " WHERE (currency_code = :currencyCode" +
                        " AND userName =:userName" +
                        " AND active =:active)",
                nativeQuery = true
        )
        public abstract Optional<UserAccountBalance> findByUserAccountBalance_UserName_And_CurrencyCode(
                String userName,
                String currencyCode,/*this is what truly worked out for me perfectly*/
                int active
        );
    
    }
    

    #3。测试并再次测试。如果问题仍然存在,请耐心等待并查看所有 你的变量和类。

    #4。如果使用选项 #3 进行故障排除仍然没有帮助,请考虑走一走,走 稍作休息,并以全新的眼光从故障排除#1中全面审视。

    我希望这会有所帮助。欢呼与和平。

    【讨论】:

      【解决方案2】:

      对于原生查询,我们可以使用

      SELECT * FROM table 
      WHERE 
                (:paramName is null OR column1 = cast(:paramName AS text)) 
      

      然后

      query.setParamter(paramName,value);

      【讨论】:

        【解决方案3】:

        这个问题很老,但如果有人需要,我仍然分享我在 Spring Boot 中使用的解决方案。

        您可以使用以下 WHERE 条件来处理 NULL 值或在 Postgres 查询中使参数可选。

        SELECT * FROM table 
        WHERE 
                  (?1 is null OR column1 = cast(?1 AS text)) 
                  AND 
                  (?2 is null OR column2 = cast(?2 AS text))
        

        如果 column1 和 column2 作为 NULL 传递,则此处整个 WHERE 条件将为 TRUE。 如果 column1 和 column2 不为 NULL,则查询中将考虑 column1 和 column2。

        ?1 为空或 column1 = ?1 : 将检查传递的值是否为空,然后整个 where 条件将为真(如果为空,则不会检查第二个条件 [column1 = null] - PG优化)

        cast(?1 AS text) : 如果出于某种原因将值作为 bytea 传递,则可能很有用。如果传递的值是真正的null,如果不强制转换,它仍然会给出“字符不同的字节”错误。

        【讨论】:

        • 此方法仅适用于 nativeQuery=false
        【解决方案4】:

        似乎 Hibernate 出于某种原因将类型参数作为 bytea(或者更确切地说,可能是 java.sql.Types.BLOB)发送,而不是让服务器推断或将其设置为文本(java.sql .Types.STRING)。 这是解决方案JPA lower() function on parameter的类似问题

        【讨论】:

          【解决方案5】:

          我认为您应该检查您的变量“userName”是否不为空。在这种情况下,我遇到了此消息。

          【讨论】:

          • 在我的情况下它可以为空。遇到这种情况怎么办?
          • 在使用变量查询的任何地方预检查 null
          • 我曾经遇到过这个问题,我解决了在查询之前将变量设置为空字符串(''),以防它为空。
          • 非常感谢@GuilhermeAlencar,我一直在努力让它发挥作用。但这不对,null 不起作用,空字符串就像它是 null 一样工作。奇怪。
          猜你喜欢
          • 1970-01-01
          • 2018-02-17
          • 2021-01-06
          • 2016-06-06
          • 1970-01-01
          • 2020-02-05
          • 1970-01-01
          • 2021-12-09
          相关资源
          最近更新 更多