Массовая вставка HQL

Я использую postgresql с спящим режимом, и я хотел бы массово вставлять данные из таблицы шаблонов в другую. Как это сделать в нативном запросе, мне понятно, но в HQL я действительно не знаю, как достичь ожидаемого результата. Я использовал синтаксис из http://docs.jboss.org/hibernate/core/3.3/reference/en/html/batch.html#batch-direct, чтобы создать мой запрос.

@NamedQuery(name="Tile.bulkLoadLevel", query="INSERT INTO Tile (x, y, game, tileOverlay, startTile, blockWalkable, sightBlocking)" +
        " SELECT t.x, t.y, :game as game, t.tileOverlay, t.startTile, t.blockWalkable, t.sightBlocking from TemplateQuestTile t")

Моя Шма:

CREATE TABLE tile
(
   x integer NOT NULL,
   y integer NOT NULL,
   blockwalkable boolean NOT NULL,
   sightblocking boolean NOT NULL,
   starttile boolean NOT NULL,
   imagepath character varying(255) NOT NULL,
   gameid bigint NOT NULL,
   CONSTRAINT tile_pkey PRIMARY KEY (gameid, x, y)
 );

Упростил мой шаблон:

   CREATE TABLE templatequesttile
   (
     x integer NOT NULL,
     y integer NOT NULL,
     blockwalkable boolean NOT NULL,
     sightblocking boolean NOT NULL,
     starttile boolean NOT NULL,
     imagepath character varying(255) NOT NULL,
     questname character varying(255) NOT NULL,
     CONSTRAINT templatequesttile_pkey PRIMARY KEY (questname, questseries, x, y)
   )

Я получаю следующую ошибку:

ERROR (SessionFactoryImpl.java:435) - Error in named query: Tile.bulkLoad
org.hibernate.QueryException: number of select types did not match those for insert [INSERT INTO Tile (x, y,    game, tileOverlay, startTile, blockWalkable, sightBlocking) SELECT t.x, t.y, :game, t.tileOverlay, t.startTile, t.blockWalkable, t.sightBlocking from net.hq.model.TemplateQuestTile t]
at org.hibernate.hql.ast.tree.IntoClause.validateTypes(IntoClause.java:115)
at org.hibernate.hql.ast.tree.InsertStatement.validate(InsertStatement.java:57)
at org.hibernate.hql.ast.HqlSqlWalker.postProcessInsert(HqlSqlWalker.java:715)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.insertStatement(HqlSqlBaseWalker.java:519)
at org.hibernate.hql.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:261)

Игра — это сущность, которая имеет длинный идентификатор, сгенерированный последовательностью.

Как видите, игры нет в моей таблице шаблонов, поэтому мне нужно будет принудительно указать идентификатор игры в моем запросе. Кто-нибудь знает, как это нужно сделать?

Заранее спасибо за ваше время, с наилучшими пожеланиями м

PS: как я называю запрос:

Query query = em.createNamedQuery("Tile.bulkLoadLevel");
query.setParameter("game", game.getGameid());
int copyiedEntities = query.executeUpdate();

Объекты:

public class Tile implements Serializable{

@Id
private int x;
@Id
private int y;
@Id
@ManyToOne
@JoinColumn(name="gameid")
private Game game;

PS: актерский состав тоже не работает.

Я думаю, вы не можете выразить этот запрос в HQL. Документация Hibernate описывает несколько ограничений запросов

@NamedQuery(name="Tile.bulkLoadLevel", query="INSERT INTO Tile (x, y, game, tileOverlay, startTile, blockWalkable, sightBlocking)" +
        " SELECT t.x, t.y, :game as game, t.tileOverlay, t.startTile, t.blockWalkable, t.sightBlocking from TemplateQuestTile t")
, особенно


person mkuff    schedule 20.01.2011    source источник


Ответы (3)


select_statement может быть любым допустимым запросом выбора HQL с оговоркой, что возвращаемые типы должны соответствовать типам, ожидаемым вставкой. В настоящее время это проверяется во время компиляции запроса, а не позволяет проверке передать базу данных.

Поскольку вы не можете выразить в запросе тот факт, что :game имеет тип Game, компиляция этого запроса никогда не будет успешной.

Вместо этого попробуйте использовать собственный SQL-запрос.

Попробуйте с:

person axtavt    schedule 20.01.2011
comment
Это неправильно. Я заставил его работать. Может быть, это потому, что у меня Hibernate 3.6, а у вас что-то более старое. Смотрите мой ответ ниже. - person mkuff; 20.01.2011
comment
Стоило попробовать, но он вылетает с исключением нулевого указателя. кажется, он не может найти класс броска в это время. приветствия - person Ryan Shillington; 23.04.2013

INSERT INTO Tile (x, y, game, tileOverlay, startTile, blockWalkable, sightBlocking) SELECT tx, ty, cast(:game as Game), t.tileOverlay, t.startTile, t.blockWalkable, t.sightBlocking от TemplateQuestTile t")

и

query.setEntity("игра", игра);

Я предполагаю, что у вас также есть класс с именем Tile, а x, y, tileOverlay... являются свойствами этого класса. Из справочных документов по спящему режиму: «Псевдосинтаксис для операторов INSERT: INSERT INTO EntityName properties_list select_statement».

Что касается функции приведения, «приведение (... как ...), где второй аргумент - это имя типа Hibernate», поэтому оно должно работать.

Я не пробовал это с сущностями, но с простыми типами (byte, integer...) он работал нормально.

Я понял, как это сделать, из комментария jorgegm выше, который, как мне хотелось бы, был его фактическим ответом, поскольку его первоначальный ответ дает NPE.

person jorgegm    schedule 09.03.2011
comment
Правильно, он падает с NPE. В качестве обходного пути он сработал, заменив «cast(:game as Game)» на «g» и добавив «, Game g, где g = :game» к предложению from. Это создает ненужное соединение, но вместо этого позволяет использовать HQL для перехода к SQLquery. - person mkuff; 25.03.2011
comment
java.lang.ExceptionInInitializerError в net.hq.process.db.PersistenceTest.setUp(PersistenceTest.java:58) в sun.reflect.NativeMethodAccessorImpl.invoke0(собственный метод) в sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) ) в sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) в java.lang.reflect.Method.invoke(Method.java:597) в org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java :44) в org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) в org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) в org.junit.internal. runners.statements.RunBefores.evaluate(RunBefores.java:27) в org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31) в org.junit.runners.ParentRunner.run(ParentRunner.java: 236) на org.eclipse.jdt.internal.junit4.runner.JUnit4TestRef erence.run(JUnit4TestReference.java:49) в org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) в org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests( RemoteTestRunner.java:467) в org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) в org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java: 390) в org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) Вызвано: java.lang.NullPointerException в java.lang.Class.forName0 (собственный метод) в java.lang. Class.forName(Class.java:169) в org.hibernate.util.ReflectHelper.classForName(ReflectHelper.java:192) в org.hibernate.type.TypeFactory.heuristicType(TypeFactory.java:279) в org.hibernate.type .TypeFactory.heuristicType(TypeFactory.java:264) в org.hibernate.hql.ast.util.SessionFactoryHelper.findFunctionReturnType(SessionFactoryHelper.java:4 00) в org.hibernate.hql.ast.util.SessionFactoryHelper.findFunctionReturnType(SessionFactoryHelper.java:392) в org.hibernate.hql.ast.tree.MethodNode.dialectFunction(MethodNode.java:103) в org.hibernate.hql .ast.tree.MethodNode.resolve(MethodNode.java:78) в org.hibernate.hql.ast.HqlSqlWalker.processFunction(HqlSqlWalker.java:979) в org.hibernate.hql.antlr.HqlSqlBaseWalker.functionCall(HqlSqlBaseWalker.java :2529) по адресу org.hibernate.hql.antlr. HqlSqlBaseWalker.selectExpr(HqlSqlBaseWalker.java:2129) в org.hibernate.hql.antlr.HqlSqlBaseWalker.selectExprList(HqlSqlBaseWalker.java:1983) в org.hibernate.hql.antlr.HqlSqlBaseWalker.selectClause(HqlSql.java) в .hibernate.hql.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:586) в org.hibernate.hql.antlr.HqlSqlBaseWalker.insertStatement(HqlSqlBaseWalker.java:510) в org.hibernate.hql.antlrq.HqlSqlBaseWalker. .java:261) в org.hibernate.hql.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:254) в org.hibernate.hql.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:185) в org.hibernate.hql. ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:136) в org.hibernate.engine.query.HQLQueryPlan.(HQLQueryPlan.java:101) в org.hibernate.engine.query.HQLQueryPlan.(HQLQueryPlan.java:80) в org .hibernate.engine.query.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.j ava:98) в org.hibernate.impl.SessionFactoryImpl.checkNamedQueries(SessionFactoryImpl.java:562) в org.hibernate.impl.SessionFactoryImpl.(SessionFactoryImpl.java:424) в org.hibernate.cfg.Configuration.buildSessionFactory(Configuration. java:1385) в org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:954) в org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:891) в org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence) .java:57) в javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:48) в javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:32) в net.hq.util.Db.(Db.java:7 ) ... еще 17 - person jorgegm; 13.04.2011

Вы хотите создать свой запрос следующим образом:

Затем позвоните

INSERT INTO Tile (x, y, game, tileOverlay, startTile, blockWalkable, sightBlocking)
SELECT t.x, t.y, g, t.tileOverlay, t.startTile, t.blockWalkable, t.sightBlocking 
  FROM TemplateQuestTile t,
       Game g
 WHERE g.id = :gameId

Я сделал это, используя Hibernate 3.6, и он работает как шарм.

query.setParameter("gameId", game.getId());

Я понимаю. Большое спасибо. Я надеялся обойти это в любом случае. Возможно, в следующем выпуске jpa. :)

person Ryan Shillington    schedule 23.04.2013