Hibernate和Java和Postgres @Enumerated(value = EnumType.STRING) - 引起:org.postgresql.util.PSQLException:int类型的错误值

时间:2018-06-12 13:38:24

标签: java postgresql hibernate jpa

我在映射中遇到异常:

@Enumerated(value=EnumType.STRING)     
public AuthenticationVendor getProvider() {
   return this.provider;
}

这是枚举

public enum AuthenticationVendor {
    LOCALDB, GOOGLE, FACEBOOK
}

异常似乎表明hibernate正在使用org.hibernate.type.EnumType$OrdinalEnumValueMapper来获取基于堆栈跟踪的值:

Caused by: org.postgresql.util.PSQLException: Bad value for type int : LOCALDB
    at org.postgresql.jdbc.PgResultSet.toInt(PgResultSet.java:2831)
    at org.postgresql.jdbc.PgResultSet.getInt(PgResultSet.java:2088)
    at org.postgresql.jdbc.PgResultSet.getInt(PgResultSet.java:2502)
    at com.zaxxer.hikari.pool.HikariProxyResultSet.getInt(HikariProxyResultSet.java)
    at org.hibernate.type.EnumType$OrdinalEnumValueMapper.getValue(EnumType.java:337)

这只是Postgres的一个问题 - 当我用H2数据库进行单元测试时,它运行正常。这是Postgres的表(注意我的@Id确实是一个字符串并且工作正常):

      Column      |            Type             | Collation | Nullable | Default | Storage  | Stats target | Description
------------------+-----------------------------+-----------+----------+---------+----------+--------------+-------------
 id               | character varying(255)      |           | not null |         | extended |              |
 created          | timestamp without time zone |           |          |         | plain    |              |
 active           | boolean                     |           | not null |         | plain    |              |
 password         | character varying(255)      |           | not null |         | extended |              |
 provider         | character varying(255)      |           |          |         | extended |              |
 salt             | bytea                       |           |          |         | extended |              |
 useremailaddress | character varying(255)      |           |          |         | extended |              |
 userphonenumber  | character varying(255)      |           |          |         | extended |              |
 username         | character varying(255)      |           | not null |         | extended |              |

这是整个实体:

@Entity
@Table(name = "app_user",
        uniqueConstraints = {
                @UniqueConstraint(columnNames = {"username"})
                        }
        )
@NamedQueries(
        @NamedQuery(name = "AppUser.findByUsername", query = "SELECT U FROM AppUser U WHERE U.username = :username")
)
public final class AppUser extends BaseEntity {
    static final SecureRandom sr = new SecureRandom();

    String username;

    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    String password;

    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    byte[] salt;

    AuthenticationVendor provider;

    String userPhoneNumber;

    String userEmailAddress;

    boolean active;

    public AppUser() {
        super();
        provider = AuthenticationVendor.LOCALDB;
    }

    public static byte[] randomSalt() {
        return new BigInteger(130, sr).toString(32).getBytes();
    }

    public static String hashPassword(byte[] salt, String password)
            throws NoSuchAlgorithmException, InvalidKeySpecException {

        KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 128);
        SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        byte[] hash = f.generateSecret(spec).getEncoded();
        Base64.Encoder enc = Base64.getEncoder();
        return enc.encodeToString(hash);
    }

    public boolean validatePassword(String maybePassword)
            throws Exception {
        try {
            String pw = hashPassword(this.salt, maybePassword);
            return pw.equals(this.getPassword());
        } catch (Exception e) {
            throw new Exception(e);
        }
    }

    public void changePassword(String newPassword)
            throws Exception {
        try {
            this.salt = randomSalt();
            this.setPassword(hashPassword(this.salt, newPassword));
        } catch (Exception e) {
            throw new Exception(e);
        }
    }

    @NotNull
    public String getUsername() {
        return this.username;
    }

    @NotNull
    public String getPassword() {
        return this.password;
    }

    public byte[] getSalt() {
        return this.salt;
    }

    @Enumerated(value=EnumType.STRING)
    public AuthenticationVendor getProvider() {
        return this.provider;
    }

    public String getUserPhoneNumber() {
        return this.userPhoneNumber;
    }

    public String getUserEmailAddress() {
        return this.userEmailAddress;
    }

    public boolean isActive() {
        return this.active;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setSalt(byte[] salt) {
        this.salt = salt;
    }

    public void setProvider(AuthenticationVendor provider) {
        this.provider = provider;
    }

    public void setUserPhoneNumber(String userPhoneNumber) {
        this.userPhoneNumber = userPhoneNumber;
    }

    public void setUserEmailAddress(String userEmailAddress) {
        this.userEmailAddress = userEmailAddress;
    }

    public void setActive(boolean active) {
        this.active = active;
    }

    public boolean equals(Object o) {
        if (o == this)
            return true;
        if (!(o instanceof AppUser))
            return false;
        final AppUser other = (AppUser) o;
        if (!other.canEqual((Object) this))
            return false;
        final Object this$username = this.getUsername();
        final Object other$username = other.getUsername();
        if (this$username == null ? other$username != null : !this$username.equals(other$username))
            return false;
        final Object this$password = this.getPassword();
        final Object other$password = other.getPassword();
        if (this$password == null ? other$password != null : !this$password.equals(other$password))
            return false;
        if (!Arrays.equals(this.getSalt(), other.getSalt()))
            return false;
        final Object this$provider = this.getProvider();
        final Object other$provider = other.getProvider();
        if (this$provider == null ? other$provider != null : !this$provider.equals(other$provider))
            return false;
        final Object this$userPhoneNumber = this.getUserPhoneNumber();
        final Object other$userPhoneNumber = other.getUserPhoneNumber();
        if (this$userPhoneNumber == null ?
                other$userPhoneNumber != null :
                !this$userPhoneNumber.equals(other$userPhoneNumber))
            return false;
        final Object this$userEmailAddress = this.getUserEmailAddress();
        final Object other$userEmailAddress = other.getUserEmailAddress();
        if (this$userEmailAddress == null ?
                other$userEmailAddress != null :
                !this$userEmailAddress.equals(other$userEmailAddress))
            return false;
        if (this.isActive() != other.isActive())
            return false;
        return true;
    }

    public int hashCode() {
        final int PRIME = 59;
        int result = 1;
        final Object $username = this.getUsername();
        result = result * PRIME + ($username == null ? 43 : $username.hashCode());
        final Object $password = this.getPassword();
        result = result * PRIME + ($password == null ? 43 : $password.hashCode());
        result = result * PRIME + Arrays.hashCode(this.getSalt());
        final Object $provider = this.getProvider();
        result = result * PRIME + ($provider == null ? 43 : $provider.hashCode());
        final Object $userPhoneNumber = this.getUserPhoneNumber();
        result = result * PRIME + ($userPhoneNumber == null ? 43 : $userPhoneNumber.hashCode());
        final Object $userEmailAddress = this.getUserEmailAddress();
        result = result * PRIME + ($userEmailAddress == null ? 43 : $userEmailAddress.hashCode());
        result = result * PRIME + (this.isActive() ? 79 : 97);
        return result;
    }

    protected boolean canEqual(Object other) {
        return other instanceof AppUser;
    }

    public String toString() {
        return "AppUser(username=" + this.getUsername() + ", provider=" + this.getProvider() +
               ", userPhoneNumber=" + this.getUserPhoneNumber() + ", userEmailAddress=" +
               this.getUserEmailAddress() + ", active=" + this.isActive() + ")";
    }
}

1 个答案:

答案 0 :(得分:1)

你需要在 Postgresql 中定义一个枚举类型:

create type authentication_vendor as enum ('LOCALDB', 'GOOGLE', 'FACEBOOK');

并在您的表中定义 providerauthentication_vendor 类型:

      Column      |            Type             | Collation | Nullable |
 id               | character varying(255)      |           | not null |
 created          | timestamp without time zone |           |          |
 active           | boolean                     |           | not null |
 password         | character varying(255)      |           | not null |
 provider         | authentication_vendor       |           |          |
 salt             | bytea                       |           |          |
 useremailaddress | character varying(255)      |           |          |
 userphonenumber  | character varying(255)      |           |          |
 username         | character varying(255)      |           | not null |

在您的实体中,您需要在类级别和列级别定义类型:

@Entity
@Table(name = "app_user",
        uniqueConstraints = {
                @UniqueConstraint(columnNames = {"username"})
                        }
        )
@NamedQueries(
        @NamedQuery(name = "AppUser.findByUsername", query = "SELECT U FROM AppUser U WHERE U.username = :username")
)
@TypeDef(name = "pgsql_enum", typeClass = PostgreSQLEnumType.class)
public final class AppUser extends BaseEntity {
    static final SecureRandom sr = new SecureRandom();

    String username;

    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    String password;

    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    byte[] salt;
    
    @Enumerated(EnumType.STRING)
    @Type(type = "pgsql_enum")
    AuthenticationVendor provider;

    String userPhoneNumber;

    String userEmailAddress;

    boolean active;

    // constructors

    // getters and setters
}