HQL Bulk insert - PullRequest
       16

HQL Bulk insert

2 голосов
/ 20 января 2011

Я использую Postgresql с Hibernate, и я хотел бы массово вставить данные из таблицы шаблонов в другую. Как это сделать в нативном Query, мне ясно, но в 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: актерский состав тоже не работает.

java.lang.ExceptionInInitializerError в net.hq.process.db.PersistenceTest.setUp (PersistenceTest.java:58) в sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Метод) в 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.JUnit4TestReference.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 (Native Метод) в 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:400) в 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 (HqlSqlBaseWalker.java:1515) в org.hibernate.hql.antlr.HqlSqlBaseWalker.query (HqlSqlBaseWalker.java:586) в org.hibernate.hql.antlr.HqlSqlBaseWalker.insertStatement (HqlSqlBaseWalker.java:510) в org.hibernate.hql.antlr.HqlSqlBaseWalker.statement (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.ulan.java: 101) в org.hibernate.engine.query.HQLQueryPlan. (HQLQueryPlan.java:80) в org.hibernate.engine.query.QueryPlanCache.getHQLQueryPlan (QueryPlanCache.java:98) в org.hibernate.actlImpI.checkNamedQueries (SessionFactoryImpl.java:562) в org.hibernate.impl.SessionFactoryImpl. (SessionFactoryImpl.java:424) в org.hibernate.cfg.Configuration.buildSessionFactory (Configuration.java:1385) в org.h.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

Ответы [ 3 ]

2 голосов
/ 09 марта 2011

Попробуйте:

INSERT INTO Tile (x, y, game, tileOverlay, startTile, blockWalkable, sightBlocking) ВЫБРАТЬ tx, ty, приведение (: игра как игра) , t.tileOverlay, t.startTile, t.blockWalkable, t.sightBlocking from TemplateQuestTile t ")

и

query.setEntity (" game ", game);

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

Что касается функции приведения," cast (... as ...), где вторым аргументом является имя Hibernatetype ", поэтому он должен работать.

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

1 голос
/ 23 апреля 2013

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

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

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

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

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

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

0 голосов
/ 20 января 2011

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

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

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

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

...