powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Миграция с Oracle на PostgreSQL. Передать параметр составного типа в хранимую через jdbс
14 сообщений из 14, страница 1 из 1
Миграция с Oracle на PostgreSQL. Передать параметр составного типа в хранимую через jdbс
    #38541070
Rebeled
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В Oracle, когда надо было передавать в хранимые массивы составных типов делали так:

Создавали оракловый тип:
Код: plsql
1.
2.
3.
4.
CREATE OR REPLACE TYPE "TEST.TEST_TYPE" as object (
    unid               number
  , name              varchar2 (100 char)
)


И тип таблица от этих типов

Код: plsql
1.
CREATE OR REPLACE TYPE "TEST.TEST_TYPE_TAB" as table of TEST.TEST_TYPE




в вызывающем коде делали маппинг этих типов через ORAData

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
public class TestSqlType implements ORAData, ORADataFactory
{
  public static final String _SQL_NAME = "TEST.TEST_TYPE";
  public static final int _SQL_TYPECODE = OracleTypes.STRUCT;

  protected MutableStruct _struct;

  private static int[] _sqlType =  { 2,12 };
  private static ORADataFactory[] _factory = new ORADataFactory[2];
protected static final TestSqlType _TestSqlTypeFactory = new TestSqlType(false);

  public static ORADataFactory getORADataFactory()
  { return _TestSqlTypeFactory; }
  /* constructor */
  protected TestSqlType(boolean init)
  { if(init) _struct = new MutableStruct(new Object[2], _sqlType, _factory); }
  public TestSqlType()
  { this(true); }
  public TestSqlType(oracle.sql.NUMBER unid, oracle.sql.CHAR name) throws SQLException
  { this(true);
    setUnid(unid);
    setName(name);
  }

  /* ORAData interface */
  public Datum toDatum(Connection c) throws SQLException
  {
    return _struct.toDatum(c, _SQL_NAME);
  }


  /* ORADataFactory interface */
  public ORAData create(Datum d, int sqlType) throws SQLException
  { return create(null, d, sqlType); }
  protected ORAData create(TestSqlType o, Datum d, int sqlType) throws SQLException
  {
    if (d == null) return null; 
    if (o == null) o = new TestSqlType(false);
    o._struct = new MutableStruct((STRUCT) d, _sqlType, _factory);
    return o;
  }
  /* accessor methods */
  public oracle.sql.NUMBER getUnid() throws SQLException
  { return (oracle.sql.NUMBER) _struct.getOracleAttribute(0); }

  public void setUnid(oracle.sql.NUMBER unid) throws SQLException
  { _struct.setOracleAttribute(0, unid); }

  public oracle.sql.CHAR getName() throws SQLException
  { return (oracle.sql.CHAR) _struct.getOracleAttribute(1); }

  public void setName(oracle.sql.CHAR name) throws SQLException
  { _struct.setOracleAttribute(1, name); }

}

public class TestSqlTypeTab implements ORAData, ORADataFactory
{
  public static final String _SQL_NAME = "TEST.TEST_SQL_TYPE_TAB";
  public static final int _SQL_TYPECODE = OracleTypes.ARRAY;

  MutableArray _array;

private static final TestSqlTypeTab _TestSqlTypeTabFactory = newTestSqlTypeTab();

  public static ORADataFactory getORADataFactory()
  { return _TestSqlTypeTabFactory; }
  /* constructors */
  public TestSqlTypeTab()
  {
    this((TestSqlType[])null);
  }

  publicTestSqlTypeTab(TestSqlTypeType[] a)
  {
    _array = new MutableArray(2002, a, TestSqlType.getORADataFactory());
  }

  /* ORAData interface */
  public Datum toDatum(Connection c) throws SQLException
  {
    return _array.toDatum(c, _SQL_NAME);
  }

  /* ORADataFactory interface */
  public ORAData create(Datum d, int sqlType) throws SQLException
  {
    if (d == null) return null;
    TestSqlTypeTab a = new TestSqlTypeTab();
    a._array = new MutableArray(2002, (ARRAY) d, TestSqlType.getORADataFactory());
    return a;
  }

  public int length() throws SQLException
  {
    return _array.length();
  }

  public int getBaseType() throws SQLException
  {
    return _array.getBaseType();
  }

  public String getBaseTypeName() throws SQLException
  {
    return _array.getBaseTypeName();
  }

  public ArrayDescriptor getDescriptor() throws SQLException
  {
    return _array.getDescriptor();
  }

  /* array accessor methods */
  public TestSqlType[] getArray() throws SQLException
  {
    return (TestSqlType[]) _array.getObjectArray(
      new TestSqlType[_array.length()]);
  }

  public void setArray(TestSqlType[] a) throws SQLException
  {
    _array.setObjectArray(a);
  }

  public TestSqlType[] getArray(long index, int count) throws SQLException
  {
    return (TestSqlType[]) _array.getObjectArray(index,
      new TestSqlType[_array.sliceLength(index, count)]);
  }

  public void setArray(TestSqlType[] a, long index) throws SQLException
  {
    _array.setObjectArray(a, index);
  }

  public TestSqlType getElement(long index) throws SQLException
  {
    return (TestSqlType) _array.getObjectElement(index);
  }

  public void setElement(TestSqlType a, long index) throws SQLException
  {
    _array.setObjectElement(a, index);
  }

}



В результате через jdbc могли передавать параметры со структурой любой сложности

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
conn.setAutoCommit(false);

                cs = (OracleCallableStatement)conn.prepareCall(
			"BEGIN TEST.PROC_TEST(?); END;");
            
                TestSqlType[] rows = new TestSqlType[2];

                rows[0] = new TestSqlType(new NUMBER(1),
                                              new CHAR("name1".getBytes("Cp1251"), chSet));
                rows[1] = new TestSqlType(new NUMBER(2),
                                              new CHAR("name2".getBytes("Cp1251"), chSet));

		//construct table
		TestSqlTypeTab tab = new TestSqlTypeTab(rows);

		cs.setORAData(1,tab);

		cs.execute();



Есть в PostgreSQL какон нибудь аналог ORAData или что нибудь попроще для реализации таких задач(передачи в качестве параметров хранимой выпуклых структур данных)?
...
Рейтинг: 0 / 0
Миграция с Oracle на PostgreSQL. Передать параметр составного типа в хранимую через jdbс
    #38541113
tadmin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Rebeled,
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
--
-- Name: barcode_process; Type: TYPE; Schema: public; Owner: -
--

CREATE TYPE barcode_process AS (
	storeplaceid int,
	requestid int,
	requestitemid int,
	containerid int,
	drawtypeid int,
	receptionid int,
	receptionitemid int,
	deliveryid int,
	shipmentid int,
	amount integer,
	isamount boolean,
	packsamount integer,
	ispacksamount boolean,
	repfactor integer,
	isrepfactor boolean,
	toprint boolean,
	personid int,
	personname character varying(128),
	modeid int,
	stateid int,
	objectid int,
	objecttypeid int,
	issystem boolean
);
CREATE FUNCTION barcodeprocess(in_sessionid public.d_uuid, in_barcode public.barcode_process, in_cursorname refcursor) RETURNS refcursor
..................
...
Рейтинг: 0 / 0
Миграция с Oracle на PostgreSQL. Передать параметр составного типа в хранимую через jdbс
    #38541119
tadmin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот только умеет ли JDBC с пользовательскими типами работать...
...
Рейтинг: 0 / 0
Миграция с Oracle на PostgreSQL. Передать параметр составного типа в хранимую через jdbс
    #38541120
Rebeled
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
tadminВот только умеет ли JDBC с пользовательскими типами работать...
Я собственно про это и спрашиваю.
...
Рейтинг: 0 / 0
Миграция с Oracle на PostgreSQL. Передать параметр составного типа в хранимую через jdbс
    #38541282
V&N
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
V&N
Гость
Rebeled, умеет.

Код: plaintext
1.
2.
3.
4.
public class MyType extends org.postgresql.util.PGobject implements java.io.Serializable, Cloneable ...

((PGConnection) connection).addDataType("my_type", Class.forName("pgadmin.MyType"));

MyType myType = (MyType)rs.getObject("colName");

смотрите исходники jdbc src/org/postgresql/geometric/PGbox.java *.java.
...
Рейтинг: 0 / 0
Миграция с Oracle на PostgreSQL. Передать параметр составного типа в хранимую через jdbс
    #38541302
Rebeled
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
V&N Rebeled, умеет.

Код: plaintext
1.
2.
3.
4.
public class MyType extends org.postgresql.util.PGobject implements java.io.Serializable, Cloneable ...

((PGConnection) connection).addDataType("my_type", Class.forName("pgadmin.MyType"));

MyType myType = (MyType)rs.getObject("colName");

смотрите исходники jdbc src/org/postgresql/geometric/PGbox.java *.java.
Спасибо, завтра попробую. Это вроде для возврата курсора, как параметр в функцию можно? В CallableStatement через setObject передавать? А массив MyType[] как?
...
Рейтинг: 0 / 0
Миграция с Oracle на PostgreSQL. Передать параметр составного типа в хранимую через jdbс
    #38541988
Rebeled
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
PLpgSql объекты:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
CREATE TYPE test.test_type AS (
  unid INTEGER,
  name CHAR(100)
);

CREATE OR REPLACE FUNCTION test.f_test_table (
  parm1 test.test_type
)
RETURNS void AS
$body$
DECLARE
BEGIN
  parm1.unid:=1;
EXCEPTION
WHEN OTHERS THEN
  parm1.unid:=2;
END;
$body$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
COST 100;



Маппинг в JAVA
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
package test;

import java.io.Serializable;
import java.math.BigDecimal;
import org.postgresql.util.PGobject;

public class  PGTestType extends PGobject implements Serializable, Cloneable
    {

        public BigDecimal unid;
        public String name;

        public PGTestType(BigDecimal _unid,String _name)
        {
            this();
            name = _name;
            unid = _unid;
        }
        public PGTestType()
        {
            unid = BigDecimal.ZERO;
        }

       public boolean   equals(Object obj)
       {
           if(obj==null)return false;
           if (obj instanceof PGTestType)
           {
               PGTestType p = (PGTestType)obj;
               if(this.unid ==null||p.unid ==null) return false;

               return this.unid.equals(p.unid);
           }

           return false;
       }

       public int hashCode(){
           return unid.intValue();
       }

       public Object  clone() throws CloneNotSupportedException
       {

           PGTestType newPG = (PGTestType) super.clone();

           newPG.unid = this.unid;
           newPG.name = this.name;

           return newPG;
       }

   }


Вызывающий код:

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
try {
            conn = HibernateUtil.getInstance().getConnection();
            ((PGConnection)conn).addDataType("test.test_type", Class.forName("test.PGTestType"));


            cs = conn.prepareCall(
                    "BEGIN test.f_test_table(?); END;");



            PGTestType t = new PGTestType(new BigDecimal("1"), "name1");
            cs.setObject(1, t, Types.OTHER);
            cs.execute();

        } catch (Exception ex) {
            System.out.println(ex);
        }



Не работает:
Код: plaintext
org.postgresql.util.PSQLException: Неизвестный тип null.
...
Рейтинг: 0 / 0
Миграция с Oracle на PostgreSQL. Передать параметр составного типа в хранимую через jdbс
    #38542048
Rebeled
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Если добавить в конструктор PGTestType
Код: java
1.
setType("test.test_type");


Выдаёт
Код: plaintext
org.postgresql.util.PSQLException: Неизвестный тип test.test_type
...
Рейтинг: 0 / 0
Миграция с Oracle на PostgreSQL. Передать параметр составного типа в хранимую через jdbс
    #38542078
tadmin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
RebeledЕсли добавить в конструктор PGTestType
Код: java
1.
setType("test.test_type");


Выдаёт
Код: plaintext
org.postgresql.util.PSQLException: Неизвестный тип test.test_type


Это потому, что тип определен в кавычках и верхним регистром:
Код: plsql
1.
CREATE OR REPLACE TYPE "TEST.TEST_TYPE"
...
Рейтинг: 0 / 0
Миграция с Oracle на PostgreSQL. Передать параметр составного типа в хранимую через jdbс
    #38542381
Rebeled
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Заработало когда test_type оказался в схеме public.
С синтаксисом:
Код: java
1.
setType("test_type");


Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
            ((PGConnection)conn).addDataType("test_type", Class.forName("com.baltinfo.lotware.pg.type.PGTestType"));


            cs = conn.prepareCall(
                    "{call test.f_test_table(?)}");



            PGTestType t = new PGTestType(new BigDecimal("3"), "name3");
            cs.setObject(1, t, Types.OTHER);
            cs.execute();


т.е. похоже на то, что он сам подставляет к типу "public.". Кто нибудь знает как это победить? Довольно критично.
Ну ещё было бы супер, если кто покажет как использовать вместо public.test_type типы таблиц и представлений, а так же пропихивать массивы этих типов.
...
Рейтинг: 0 / 0
Миграция с Oracle на PostgreSQL. Передать параметр составного типа в хранимую через jdbс
    #38542628
Rebeled
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
С массивами разобрался:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
            ((PGConnection)conn).addDataType("test_type", Class.forName("test.PGTestType"));


            cs = conn.prepareCall(
                    "{call test.f_test_table(?)}");


            PGTestType[] arr = new PGTestType[2];
            PGTestType t1 = new PGTestType(new BigDecimal("1"), "name1", new Date(), "clob1");
            arr[0]=t1;
            PGTestType t2 = new PGTestType(new BigDecimal("2"), null, new Date(), "clob2");
            arr[1]=t2;
            cs.setArray(1, conn.createArrayOf("test_type",arr));
            cs.execute();


На сладкое хотелось бы всё таки разобраться с типами не из public, передачей таблицы/представления как типа и возможно ли в этой схеме сериализовать из byte[] в BYTEA в
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
  public String  getValue()
    {
            SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");

            return "("+
                    unid.toString() + "," +
                    (name==null?"":name.toString())+ "," +
                    (date==null?"":sdf.format(date))+ "," +
                   // (blob==null||blob.length == 0?"":new String(blob,"utf-8"))+ "," +
                    (clob==null?"":clob)+
                    ")";


    }
...
Рейтинг: 0 / 0
Миграция с Oracle на PostgreSQL. Передать параметр составного типа в хранимую через jdbс
    #38544205
Hawkmoon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
RebeledНа сладкое хотелось бы всё таки разобраться с типами не из public...

В сторону
5.7.3. The Schema Search Path
смотрели?
...
Рейтинг: 0 / 0
Миграция с Oracle на PostgreSQL. Передать параметр составного типа в хранимую через jdbс
    #38544303
Rebeled
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Hawkmoon,

Ага, вероятно поможет, хоть и грубовато. Но проблема с сериализацией важнее. Вероятно всё таки придётся отказаться от такого подхода.
...
Рейтинг: 0 / 0
Миграция с Oracle на PostgreSQL. Передать параметр составного типа в хранимую через jdbс
    #38545560
V&N
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
V&N
Гость
Rebeled, можно :D, но будьте внимательными к одинаковым именам в разных схемах
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
    public static void main(String[] args) throws ClassNotFoundException {
        Class.forName("org.postgresql.Driver");
        try (java.sql.Connection connection = java.sql.DriverManager.getConnection("jdbc:postgresql:postgres", "postgres", "")) {
            connection.setAutoCommit(false);
            connection.createStatement().execute(""
                    + "drop schema if exists test cascade;\n"
                    + "create schema test;\n"
                    + "drop type if exists test.my_type cascade;\n"
                    + "create type test.my_type as (foo int, bar varchar);\n"
                    + "create or replace function test.test_my_type(variadic p_my_type test.my_type[])\n"
                    + "  returns setof test.my_type as\n"
                    + "$$   \n"
                    + "declare\n"
                    + "  m_my_type test.my_type;\n"
                    + "begin\n"
                    + "  if p_my_type is null\n"
                    + "  then\n"
                    + "    return;\n"
                    + "  end if;\n"
                    + "  foreach m_my_type in array p_my_type\n"
                    + "  loop\n"
                    + "    return next m_my_type;\n"
                    + "  end loop;\n"
                    + "  end;$$\n"
                    + "language plpgsql volatile;");

            java.util.Map<String, Class<?>> map = connection.getTypeMap();
            if (map == null) {
                map = new java.util.HashMap<>();
                connection.setTypeMap(map);
            }
            connection.getTypeMap().put("test.my_type", PGMyType.class);

            java.util.List<PGMyType> myTypes = new java.util.ArrayList<>();
            
            for (int i = 0; i < 10; i++) {
                myTypes.add(new PGMyType(i, i + "-\\\"test: foo \\,bar -- /*$'" + i + "\\\""));
            }
            try (java.sql.PreparedStatement pstm = connection.prepareStatement("select (test.test_my_type(variadic ?)).*")) {
                pstm.setObject(1, connection.createArrayOf("my_type", myTypes.toArray())); //тут может быть блуждающая проблема, если одно и тоже имя в разных схемах
                try (java.sql.ResultSet rs = pstm.executeQuery()) {
                    while (rs.next()) {
                        if (rs.isFirst()) {
                            System.out.printf("%s\t|%s\n", rs.getMetaData().getColumnName(1), rs.getMetaData().getColumnName(2));
                            System.out.printf("--------+---------------------------\n");
                        }
                        System.out.printf("%s\t|%s\n", rs.getObject(1), rs.getObject(2));
                    }
                }
            }
            connection.rollback();
            
        } catch (java.sql.SQLException ex) {
            ex.printStackTrace();
        }
    }
    
    private static class PGMyType extends org.postgresql.util.PGobject {
        
        public int foo;
        public String bar;
        
        public PGMyType() {
            this.setType("test.my_type");
        }
        
        public PGMyType(int foo, String bar) {
            this();
            this.foo = foo;
            this.bar = bar;
        }
        
        @Override
        public String getValue() {
            return "(" + foo + "," + bar + ")";
        }
    }

...
Рейтинг: 0 / 0
14 сообщений из 14, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Миграция с Oracle на PostgreSQL. Передать параметр составного типа в хранимую через jdbс
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]