Как использовать пользовательский тип PostgreSQL в качестве вложенного POJO в jdbi?JAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Как использовать пользовательский тип PostgreSQL в качестве вложенного POJO в jdbi?

Сообщение Anonymous »

Я пытаюсь сделать что-то, что, по моему мнению, должно быть относительно простым с помощью JDBI v3 (используя расширения sql-object и postgres).
У меня есть класс Item:< /p>

Код: Выделить всё

public class Item {
private String itemNumber;
private Dimension3D dimensions;
}
Класс Dimension3D:

Код: Выделить всё

public class Dimension3D {
private BigDecimal width, length, height;
private LengthUnit lengthUnit; // This is an enum, defaults to INCH.
// Getters and setters.
}
Я использую следующие схемы таблиц для элементов:

Код: Выделить всё

@SqlUpdate("""
CREATE TABLE items  (
item_number VARCHAR(7) NOT NULL PRIMARY KEY CHECK (item_number ~ '^[0-9]{6}[ab]?$'),
dimensions dimension_3d NOT NULL DEFAULT (0, 0, 0, 'inch'),
);
""")
void createTable();
Тип Dimension_3d создается следующим образом:

Код: Выделить всё

@SqlScript("""
CREATE TYPE spatial_unit AS ENUM ('inch', 'metric');

CREATE TYPE dimension_3d AS (
width numeric,
length numeric,
height numeric,
unit spatial_unit
);
""")
void createTypes();
Я пытаюсь создать метод InsertItem, который принимает POJO Item:

Код: Выделить всё

@SqlUpdate("insert into items (item_number, dimensions) " +
"values (:itemNumber, :dimensions)")
@RegisterColumnMapper(Dimension3DColumnMapper.class)
void insertItem(@BindBean Item item);
Чтобы попытаться выполнить эту работу, у меня есть указанный выше Dimension3DColumnMapper (не уверен, что это необходимо):

Код: Выделить всё

public class Dimension3DColumnMapper implements ColumnMapper {
@Override
public Dimension3D map(ResultSet r, int columnNumber, StatementContext ctx) throws SQLException {
return new Dimension3D(r.getBigDecimal("length"), r.getBigDecimal("width"), r.getBigDecimal("height"), LengthUnit.INCH);
}
}
Наконец, я называю эти методы следующим образом:

Код: Выделить всё

@Test
public void testCreateTables(Jdbi jdbi) {
jdbi.installPlugin(new SqlObjectPlugin());
jdbi.installPlugin(new PostgresPlugin());
jdbi.withHandle(handle -> {
handle.registerArgument(new Dimension3DArgumentFactory());
handle.configure(PostgresTypes.class, pt -> pt.registerCustomType(Dimension3DPGType.class, "dimension_3d"));
handle.attach(ItemQueries.class).createTypes();
handle.attach(ItemQueries.class).insertItem(new Item("00001", new Dimension3D(new BigDecimal("1"), new BigDecimal("1"), new BigDecimal("1"), LengthUnit.INCH));
});
}
Моя попытка сделать эту работу беспроблемной привела меня к регистрации пользовательской ArgumentFactory, определенной следующим образом:

Код: Выделить всё

public class Dimension3DArgumentFactory extends AbstractArgumentFactory {

public Dimension3DArgumentFactory() {
super(Types.NUMERIC);
}

@Override
protected Argument build(Dimension3D value, ConfigRegistry config) {
return (position, statement, ctx) ->  {
statement.setBigDecimal(position, value.getLength());
statement.setBigDecimal(position + 1, value.getWidth());
statement.setBigDecimal(position + 2, value.getHeight());
};
}
}
Я также пытался зарегистрировать пользовательский тип Dimension_3d (как показано выше):

Код: Выделить всё

public class Dimension3DPGType extends PGobject {
private Dimension3D dimension3D;

public Dimension3DPGType(BigDecimal length, BigDecimal width, BigDecimal height) {
this();
this.dimension3D = new Dimension3D(length, width, height, LengthUnit.INCH);
}

public Dimension3DPGType() {
setType("dimension_3d");
}

public BigDecimal getWidth() {
return dimension3D.getWidth();
}

public void setWidth(BigDecimal width) {
dimension3D = new Dimension3D(width, dimension3D.getLength(), dimension3D.getHeight(), LengthUnit.INCH);
}

public BigDecimal getLength() {
return dimension3D.getLength();
}

public void setLength(BigDecimal length) {
dimension3D = new Dimension3D(getWidth(), length, dimension3D.getHeight(), LengthUnit.INCH);
}

public BigDecimal getHeight() {
return dimension3D.getHeight();
}

public void setHeight(BigDecimal height) {
dimension3D = new Dimension3D(dimension3D.getWidth(), dimension3D.getLength(), height, LengthUnit.INCH);
}

@Override
public String getValue() {
return "(" + getWidth() + "," + getLength() + "," + getHeight() + ")";
}

@Override
public void setValue(String value) {
PGtokenizer t = new PGtokenizer(PGtokenizer.removePara(value), ',');

BigDecimal length = new BigDecimal(t.getToken(0));
BigDecimal width = new BigDecimal(t.getToken(1));
BigDecimal height = new BigDecimal(t.getToken(2));
dimension3D = new Dimension3D(length, width, height, LengthUnit.INCH);
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Dimension3DPGType that)) {
return false;
}
if (!super.equals(o)) {
return false;
}
return Objects.equals(dimension3D, that.dimension3D);
}

@Override
public int hashCode() {
return dimension3D.hashCode();
}
}
Я пробовал это с регистрацией ColumnMapper, ArgumentFactory и пользовательского типа или без нее.
Текущее исключение, с которым я столкнулся:
Текущее исключение, с которым я столкнулся:
р>

Код: Выделить всё

[ERROR]   DatabaseTest.testCreateTables:21->lambda$testCreateTables$1:29 » UnableToExecuteStatement org.postgresql.util.PSQLException: ERROR: column "dimensions" is of type dimension_3d but expression is of type numeric
Hint: You will need to rewrite or cast the expression.
Попытка исправить это с помощью приведения, как показано ниже:

Код: Выделить всё

@SqlUpdate("insert into items (item_number, dimensions) "  +
"values (:itemNumber, CAST(:dimensions AS dimension_3d))")
@RegisterColumnMapper(Dimension3DColumnMapper.class)
void insertItem(@BindBean Item item);

затем выдает исключение:

Код: Выделить всё

DatabaseTest.testCreateTables:21->lambda$testCreateTables$1:29 » UnableToExecuteStatement org.postgresql.util.PSQLException: ERROR: cannot cast type numeric to dimension_3d
Для справки я использую следующие версии зависимостей:

Код: Выделить всё

org.jdbi
jdbi3-core
3.47.0


org.jdbi
jdbi3-sqlobject
3.47.0


org.jdbi
jdbi3-postgres
3.47.0


org.postgresql
postgresql
42.7.4


org.jdbi
jdbi3-testing
3.47.0
test


de.softwareforge.testing
pg-embedded
5.2.0
test

Большое спасибо за любую помощь!


Подробнее здесь: https://stackoverflow.com/questions/791 ... jo-in-jdbi
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»