Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / Hibernate generator без таблицы / 25 сообщений из 34, страница 1 из 2
27.12.2016, 16:07
    #39376209
ivanra
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate generator без таблицы
Возникла задача генерировать последовательные уникальные id для нетабличных данных. В проекте используется hibernate, поэтому решено было использовать готовые механизмы. Как выяснилось, hibernate не предоставляет прямого доступа к генераторам. Копание в исходниках привело к такому коду:
Код: 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.
@TableGenerator(name="doc-generator", table="ids", pkColumnValue="seq_doc_generator", allocationSize=0x10)
// таблица-заглушка
@Entity
@Table(name="dummy_doc")
public class DummyDoc {
	private Long id;
	@Id
	@GeneratedValue(strategy=GenerationType.TABLE, generator="doc-generator")
	public Long getId() {
		return id;
	}
	public void setId(Long id) {
		this.id = id;
	}
}

/// и где-то в коде
	public Long nextId() {
		SessionFactoryImplementor sfi = (SessionFactoryImplementor)sessionFactory;
		IdentifierGenerator generator = sfi.getIdentifierGenerator(DummyDoc.class.getName());
		Session session = sessionFactory.getCurrentSession();
		Long value = (Long)generator.generate((SessionImplementor)session, null);
		return value;
	}


Что не нравится:
- если мы хотим переносимости, и чтобы всё само генерировалось, то надо объявлять
Код: xml
1.
<prop key="hibernate.hbm2ddl.auto">update</prop>

В этом случае генерируется ненужная таблица DUMMY_DOC, на каждый генератор - своя. Ну это ладно, можно обойти, не объявлять автоапдейт, и генерировать таблицу IDS руками, благо ничего там сложного нет
- использование непубличных интерфейсов SessionFactoryImplementor и SessionImplementor . Вот это неприятно, интерфейсы эти меняются, в разных версиях хибернейт они разные. Тоже можно полечить, вызвав соответствующие методы рефлексией, но как-то это некрасиво.

Есть ли более верное решение?
...
Рейтинг: 0 / 0
27.12.2016, 16:19
    #39376219
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate generator без таблицы
ivanra,

А почему нельзя тупо SQL выполнить для sequence?
...
Рейтинг: 0 / 0
27.12.2016, 16:28
    #39376226
ivanra
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate generator без таблицы
Можно, но не хочется разруливать диалекты.
Есть некоторая неопределеннсть с сервером, скорее всего это будет mssql или mysql, а там и генераторов то нет. Короче, хочется всё, что может поменяться, вынести в конфиги (аннотации это я для простоты привел), а там чтобы программа сама сгенерировала что надо, в зависимости от диалекта и заданной стратегии. У хибернейт это неплохо получается.
...
Рейтинг: 0 / 0
27.12.2016, 16:32
    #39376234
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate generator без таблицы
ivanra,

Можно в рантайме вытащить диалект и у него вызвать метод типа getSelectSequenceNextValString()
...
Рейтинг: 0 / 0
27.12.2016, 16:54
    #39376255
ivanra
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate generator без таблицы
не лучше.
- Dialect всё равно надо вытаскивать через SessionFactoryImplementor
- sequence стратегия может быть неприменима к данному диалекту

Есть еще вариат с помощью deprecated метода получить фабрику генераторов, тогда можно обойтись без таблицы-пустышки, но писанины врядли будет меньше
Код: java
1.
2.
3.
		SessionFactoryImplementor sfi = (SessionFactoryImplementor)sessionFactory;
		IdentifierGeneratorFactory igf = sfi.getIdentifierGeneratorFactory();
		igf.createIdentifierGenerator(strategy, type, config)
...
Рейтинг: 0 / 0
27.12.2016, 17:13
    #39376276
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate generator без таблицы
ivanraВозникла задача генерировать последовательные уникальные id для нетабличных данных.
переведи задачу.
На момент разработки не знаете БД или что?
...
Рейтинг: 0 / 0
27.12.2016, 17:26
    #39376285
ivanra
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate generator без таблицы
Petro123ivanraВозникла задача генерировать последовательные уникальные id для нетабличных данных.
переведи задачу.
На момент разработки не знаете БД или что?
Не знаем, база будет та, которую заказчик использует в хранилище jackrabbit jcr, скорее всего mysql (sequence нет). В данном случае она идет как бесплатный довесок (какая-то база там обязательно должна быть).
Генератор, в принципе, можно было бы хранить просто в файле. Но не хочется разводить писанину с синхронизацией, а просто взять готовый отлаженный механизм. Генератор из hibernate - как вариант.
...
Рейтинг: 0 / 0
27.12.2016, 17:51
    #39376303
questioner
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate generator без таблицы
ivanraНе знаем, база будет та, которую заказчик использует в хранилище jackrabbit jcr, скорее всего mysql (sequence нет).

cq5 старой версии что ли?

jackrabbit это ж вроде самом по себе хранение данных альтернативное реляционному. каким боком тут база?
...
Рейтинг: 0 / 0
27.12.2016, 18:02
    #39376312
ivanra
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate generator без таблицы
questioner jackrabbit это ж вроде самом по себе хранение данных альтернативное реляционному. каким боком тут база?
а Persistent Manager? Да, возможны варианты, но в данном случае будет обязательно использоваться Database PM
...
Рейтинг: 0 / 0
27.12.2016, 20:12
    #39376346
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate generator без таблицы
ivanraскорее всего mysql (sequence нет).
ну дак в половине баз нет сиквенсов, но есть счётчик-поле.
Как половина программистов на них работает и не жужжит?
Я по прежнему не понял проблему.
...
Рейтинг: 0 / 0
27.12.2016, 20:13
    #39376347
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate generator без таблицы
ivanraГенератор, в принципе, можно было бы хранить просто в файле.
смотри выше - есть тип поля счетчик.
...
Рейтинг: 0 / 0
27.12.2016, 20:15
    #39376348
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate generator без таблицы
questionerjackrabbit это ж вроде самом по себе хранение данных альтернативное реляционному. каким боком тут база?
ну ТС даёт. Любая БД по ТЗ. Да ещё реляционная и НЕрялиционная).
...
Рейтинг: 0 / 0
28.12.2016, 09:38
    #39376571
ivanra
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate generator без таблицы
Petro123,
если хочется ответить, прошу внимательней читать вопрос, он в самом начале. Нужен проверенный генератор последовательных значений не для поля в таблице . Такой, как генератор/sequence в sql сервере - конкурентный, с сохранением состояния. Желательно настраиваемый через конфигурационные файлы.
По условиям задачи имеется SQL сервер, хотя это тут не главное. Я привел вариант решения с использованием механизмов хибернейт. Всего 5 строчек кода, но с хаками. Есть другие варианты?
...
Рейтинг: 0 / 0
28.12.2016, 12:56
    #39376805
Alexey Tomin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate generator без таблицы
ivanraВозникла задача генерировать последовательные уникальные id для нетабличных данных.

А рамках чего уникальные?
Например если в рамках хоста и может быть несколько инстансов то можно сделать такой вариант:

AtomicLong id = new AtomicLong(processPID * CONST1 + System.currentTimeMillis() * CONST2);
CONST1 и CONST2 подбираем так, чтобы заполнить старшые биты long'а.

Далее id.getAndIncrement() (он на тактик быстрее incrementAndGet()).

Если хостов несколько, но, к пимеру, на каждом один инстанс- заменяем processPID на hostId (не IP, а уникальный у тебя ID).
...
Рейтинг: 0 / 0
28.12.2016, 12:58
    #39376808
Alexey Tomin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate generator без таблицы
Alexey TominAtomicLong id = new AtomicLong(processPID * CONST1 + System.currentTimeMillis() * CONST2);

Да, время надо уменьшить, конечно - NULL_DATE задаётся перед выкладкой в прод.
Код: java
1.
AtomicLong id = new AtomicLong(processPID * CONST1 + (System.currentTimeMillis() - NULL_DATE) * CONST2);
...
Рейтинг: 0 / 0
28.12.2016, 13:39
    #39376863
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate generator без таблицы
ivanraпрошу внимательней читать вопрос
нет это вы извольте писать постановку задачи, а не её решение.
Из постановки у вас 3 слова:
авторВозникла задача генерировать последовательные уникальные id для нетабличных данных.
всё остальное - это Ваше решение придуманное в голове.
Итого сначала:
- для кого ID?
Alexey Tomin уже выше вас спросил.
- в рамках чего уникальность?
...
Рейтинг: 0 / 0
28.12.2016, 13:44
    #39376866
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate generator без таблицы
ivanraНужен проверенный генератор последовательных значений не для поля в таблице . Такой, как генератор/sequence в sql сервере - конкурентный, с сохранением состояния.
опять двойка.
По своим свойствам, sequence ничем не отличается от типа поля счетчик.
Т.к. обычно на каждую таблу назначается только один sequence.
Т.е. он только повторяет или эмулирует поле счетчик.
...
Рейтинг: 0 / 0
28.12.2016, 14:57
    #39376947
ivanra
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate generator без таблицы
Petro123,
мне, например, неизвестен способ получения значения типа поля счетчик без вставки в таблицу. Было бы интересно увидеть (особенно - без таблицы).

Насчет уникальности ID: нужна уникальность в рамках хранилища (используется jackrabbit). Клиентов на данный момент 4, некоторые являются серверами приложений. Напрашивается решение в виде сервиса, который будет раздавать эти id, работающего на том же сервере, где хранилище. Но есть нюансы (некоторые клиенты сильно legacy, vb6 и delphi, чтоб было понятно на чем и когда они написаны).
Что касается реализации, то использование возможностей sql сервера лежит на поверхности. Если в сервере есть sequence - отлично, если нет, то берем TableGenerator, и там по возможности используется select for update - коллизий тоже не будет.
Да, hibernate в данном случае - это из пушки по воробью, но код очень короткий, надежный и покрывает все варианты использования. Кстати, выяснилось, что есть аннотация @Subselect, благодаря которой таблица-заглушка не генерируется.
Вот как выглядит это сейчас (пример с улучшенным TableGenerator)
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
// класс заглушка
@GenericGenerator(
		name = "doc_generator",
		strategy = "org.hibernate.id.enhanced.TableGenerator",
		parameters = {
				@Parameter(name = "segment_value", value = "seq_doc_generator"),
				@Parameter(name = "increment_size", value = "64"),
		})
@Entity 
@Subselect("")
public class DummyDoc {
	@Id @GeneratedValue(generator="doc_generator")
	private Long id;
}
// получение уникального значения
	@Transactional
	public Long nextId() {
		SessionFactoryImplementor sfi = (SessionFactoryImplementor)sessionFactory;
		IdentifierGenerator generator = sfi.getIdentifierGenerator(DummyDoc.class.getName());
		Session session = sessionFactory.getCurrentSession();
		return (Long)generator.generate((SessionImplementor)session, null);
	}
...
Рейтинг: 0 / 0
28.12.2016, 15:10
    #39376964
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate generator без таблицы
ivanraмне, например, неизвестен способ получения значения типа поля счетчик без вставки в таблицу. Было бы интересно увидеть (особенно - без таблицы).
ещё раз.
sequence - это то же поле счётчик в таблице. Только табла системная внутри БД. И наверх выведено API в виде sequence.
Т.е. вместо sequence можете свободно вставлять по одному полю в спец.таблицу.

ivanraНасчет уникальности ID: нужна уникальность в рамках хранилища (используется jackrabbit). Клиентов на данный момент 4, некоторые являются серверами приложений.
т.е. данные распределённые и есть гетерогенные транзакции?
ivanraНо есть нюансы (некоторые клиенты сильно legacy, vb6 и delphi, чтоб было понятно на чем и когда они написаны).
конкретнее.
- дельфи что? Делает JOIN с Id? Какая разница кто клиент?
...
Рейтинг: 0 / 0
28.12.2016, 15:34
    #39376983
ivanra
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate generator без таблицы
Petro123,
утверждение насчет хранения sequence в таблицах выдают вас как юниора, по крайней мере, в sql.
Но вопрос был в другом: как получить значение автоинкремента без вставки в таблицу? Конкретный код, например, в MSSQL. А без таблицы?
...
Рейтинг: 0 / 0
28.12.2016, 15:52
    #39377005
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate generator без таблицы
ivanraутверждение насчет хранения sequence в таблицах выдают вас как юниора, по крайней мере, в sql.
ваша боязнь использовать тип поля счетчик - тоже пионерство).
"Расписали".
...
Рейтинг: 0 / 0
28.12.2016, 18:22
    #39377152
ivanra
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate generator без таблицы
:)
Кстати, а вот рояль в кустах. Чтобы получить значение автоинкремента без вставки записи, надо сначала её вставить, а затем откатить транзакцию.
Но всё равно требуется таблица.
...
Рейтинг: 0 / 0
28.12.2016, 19:07
    #39377180
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate generator без таблицы
ivanra,
упрямый))
Ты в оперативке ID держать будешь?
Надёжно?
...
Рейтинг: 0 / 0
29.12.2016, 02:22
    #39377339
booby
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate generator без таблицы
ivanraPetro123,
утверждение насчет хранения sequence в таблицах выдают вас как юниора, по крайней мере, в sql.
Но вопрос был в другом: как получить значение автоинкремента без вставки в таблицу? Конкретный код, например, в MSSQL. А без таблицы?

какой кошмар невероятной продвинутости.

без таблицы нет надежно продвигаемого вперед и синхронизированного сиквенса.
Вы после выключения питания и перезапуска системы с какого значения продолжать изволите? не юниор вы наш
...
Рейтинг: 0 / 0
29.12.2016, 06:23
    #39377360
Alexey Tomin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate generator без таблицы
boobyivanraPetro123,
утверждение насчет хранения sequence в таблицах выдают вас как юниора, по крайней мере, в sql.
Но вопрос был в другом: как получить значение автоинкремента без вставки в таблицу? Конкретный код, например, в MSSQL. А без таблицы?

какой кошмар невероятной продвинутости.

без таблицы нет надежно продвигаемого вперед и синхронизированного сиквенса.
Вы после выключения питания и перезапуска системы с какого значения продолжать изволите? не юниор вы наш

Существует масса способов решения этого. И "таблица значений последовательностей"- одно из них.
Как сделано в firebird/postgreSQL/mysql желающие могут посмотреть. Как в oracle/mssql/db2 - только гадать.
Так что умерьте пыл, горячие финские парни :)
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / Hibernate generator без таблицы / 25 сообщений из 34, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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