错误:格式错误的记录文字:-JDBC插入具有自定义类型数组的数据

问题描述 投票:0回答:1

我想用JDBC将数据插入PostgreSQL,并且数据包含一个自定义类型的数组。当我尝试插入并出现错误时。

谁能指出我在哪里做错了?

String query = "INSERT INTO fitness_club (club_id, club_brand, club_name, latitude, longitude, club_status, club_home_url, address, open_hour) VALUES(?, ?::fitness_brand, ?, ?, ?, ?, ?, ?, ?)";

            PreparedStatement pst = conn.prepareStatement(query);

            pst.setInt(1, firstClub.getClubId());
            pst.setString(2, firstClub.getBrand().toString());
            pst.setString(3, firstClub.getDescription());
            pst.setDouble(4, firstClub.getLatitude());
            pst.setDouble(5, firstClub.getLongitude());
            pst.setInt(6, firstClub.getClubStatus());
            pst.setString(7, firstClub.getClubHomeUrl());
            pst.setString(8, firstClub.getAddress());

            Array arrayOpenHour = conn.createArrayOf("open_hour", firstClub.getOpenHours().toArray());

            pst.setArray(9, arrayOpenHour);

            ResultSet saveRS = pst.executeQuery();

这是错误消息

org.postgresql.util.PSQLException: ERROR: malformed record literal: "OpenHour@342c38f8"
  Detail: Missing left parenthesis.
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2510)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2245)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:311)

自定义类型

public class OpenHour {

    DayOfWeek day;

    String time;

}

数据表

create table fitness_club
(
    club_uid      uuid             not null
        constraint fitness_club_pkey
            primary key,
    club_brand    fitness_brand    not null,
    club_id       integer          not null,
    club_name     varchar(500)     not null,
    latitude      double precision not null,
    longitude     double precision not null,
    club_status   integer,
    club_home_url varchar(500),
    zip_code      varchar(500),
    address       varchar(500),
    city          varchar(500),
    state         us_state,
    open_hour     open_hour[],
    constraint brand_id_constrain
        unique (club_brand, club_id)
);
create type open_hour as
(
    day   week_day,
    hours varchar(50)
);

其他类型使用的自定义类型

create type week_day as enum ('MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY', 'FRIDAY', 'SATURDAY', 'SUNDAY');
java postgresql jdbc
1个回答
0
投票

我有相同的错误,似乎是createArrayOf中的序列化问题。我更改了解决方案,以JSON格式发送了文本。

我分享我的解决方案,希望它对您有用。

1.-模型

订购

@Getter
@Setter
@ToString
public class Order {
    private String orderId;
    private String customerId;
    private Date createdAt;
    private List<OrderProduct> orderProductList;
    private Double amountOrder;

    public Double getAmountOrder() {
        return orderProductList.stream().mapToDouble(OrderProduct::getAmount).sum();
    }
}

OrderProduct

@Getter
@Setter
@ToString
@AllArgsConstructor
public class OrderProduct implements Serializable {

    private static final long serialVersionUID = 1L;

    private int orderProductId;
    private int quantity;
    private String productId;
    private Double productPrice;

    Double getAmount() {
        return productPrice.doubleValue() * this.getQuantity();
    }
}

2.-连接并将数据发送到Postgresql,检查参数5

@Repository
public class OrderRepositoryAdapter implements CreateOrderPort 
{

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public void createOrder(Order order) throws GlobalException {

        final String procedureCall = "{ ? = call create_order(?, ?, ?, ?)}";

        try (Connection connection = jdbcTemplate.getDataSource().getConnection();
             CallableStatement callableStatement = connection.prepareCall(procedureCall)
        ) {
            Gson gson = new Gson();
            String json = gson.toJson(order.getOrderProductList());

            callableStatement.registerOutParameter(1, Types.BIGINT);
            callableStatement.setString(2, order.getCustomerId());
            callableStatement.setTimestamp(3, new java.sql.Timestamp(order.getCreatedAt().getTime()));
            callableStatement.setDouble(4, order.getAmountOrder());
            callableStatement.setString(5, json);

            callableStatement.execute();

            order.setOrderId(Long.toString(callableStatement.getLong(1)));
        } catch (Exception e) {
            throw new GlobalException("Exception createOrder: " + e.getMessage());
        }
    }
}

3- Postgresql中的函数,检查参数“ p_order_product”

CREATE OR REPLACE FUNCTION public.create_order(
    p_customer_id character varying,
    p_created_at timestamp with time zone,
    p_amount_order double precision,
    p_order_product text)
    RETURNS bigint
    LANGUAGE 'plpgsql'

AS $BODY$
DECLARE
    p_order_id bigint;
    p_order_product_id bigint;
    p_json json;
BEGIN
    p_order_id := nextval('order_id_seq');
    INSERT INTO public."ORDERS"(
        order_id, customer_id, created_at, amount_order)
    VALUES (p_order_id, p_customer_id, p_created_at, p_amount_order);

    FOR p_json IN SELECT * FROM json_array_elements(p_order_product::json)
    LOOP
        p_order_product_id := nextval('order_product_id_seq');
            INSERT INTO public."ORDERS_PRODUCTS"(
                order_product_id, quantity, product_id, product_price, order_id)
            VALUES (p_order_product_id, CAST (p_json->>'quantity' AS bigint) , p_json->>'productId', CAST(p_json->>'productPrice' AS double precision), p_order_id);
    END LOOP;

    RETURN p_order_id;

END;
$BODY$;

4.- API剩余

http://localhost:3002/v1/orders

{
    "customerId":"5ed047dda2923f1ac2c64463",
    "createdAt":"2020-06-06T00:10:12",
    "orderProductList": 
    [{
            "quantity":"2",
            "productId":"5ed31ddb669529409edc2fd0",
            "productPrice": 1099.51

    },{
            "quantity":"1",
            "productId":"5ed31cb5669529409edc2fcf",
            "productPrice": 2199.99

    }]

}

5.- Postgresql中的表

enter image description here

enter image description here

6.-您可以在我的GitHub存储库中查看完整的示例

https://github.com/JonathanM2ndoza/Hexagonal-Architecture-DDD/tree/master/Order

© www.soinside.com 2019 - 2024. All rights reserved.