2011-01-20 228 views
2

我使用postgresql與休眠,我想批量插入數據從模板表到另一個。如何在本機查詢中做到這一點對我來說很清楚,但在HQL中我並不真正知道如何達到我的預期結果。 我用http://docs.jboss.org/hibernate/core/3.3/reference/en/html/batch.html#batch-direct的語法來創建我的查詢。HQL批量插入

@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) 
); 

Simplyfied我的模板:

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) 

遊戲是一種具有悠久的標識符的實體由序列生成。

正如你所看到的遊戲不在我的模板表中,所以我需要強制遊戲ID進入我的查詢。有誰知道這是怎麼做的?

預先感謝您的時間, 問候 米

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 at net.hq.process.db.PersistenceTest.setUp(PersistenceTest.java:58) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27) at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31) at org.junit.runners.ParentRunner.run(ParentRunner.java:236) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) Caused by: java.lang.NullPointerException at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:169) at org.hibernate.util.ReflectHelper.classForName(ReflectHelper.java:192) at org.hibernate.type.TypeFactory.heuristicType(TypeFactory.java:279) at org.hibernate.type.TypeFactory.heuristicType(TypeFactory.java:264) at org.hibernate.hql.ast.util.SessionFactoryHelper.findFunctionReturnType(SessionFactoryHelper.java:400) at org.hibernate.hql.ast.util.SessionFactoryHelper.findFunctionReturnType(SessionFactoryHelper.java:392) at org.hibernate.hql.ast.tree.MethodNode.dialectFunction(MethodNode.java:103) at org.hibernate.hql.ast.tree.MethodNode.resolve(MethodNode.java:78) at org.hibernate.hql.ast.HqlSqlWalker.processFunction(HqlSqlWalker.java:979) at org.hibernate.hql.antlr.HqlSqlBaseWalker.functionCall(HqlSqlBaseWalker.java:2529) at org.hibernate.hql.antlr.HqlSqlBaseWalker.selectExpr(HqlSqlBaseWalker.java:2129) at org.hibernate.hql.antlr.HqlSqlBaseWalker.selectExprList(HqlSqlBaseWalker.java:1983) at org.hibernate.hql.antlr.HqlSqlBaseWalker.selectClause(HqlSqlBaseWalker.java:1515) at org.hibernate.hql.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:586) at org.hibernate.hql.antlr.HqlSqlBaseWalker.insertStatement(HqlSqlBaseWalker.java:510) at org.hibernate.hql.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:261) at org.hibernate.hql.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:254) at org.hibernate.hql.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:185) at org.hibernate.hql.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:136) at org.hibernate.engine.query.HQLQueryPlan.(HQLQueryPlan.java:101) at org.hibernate.engine.query.HQLQueryPlan.(HQLQueryPlan.java:80) at org.hibernate.engine.query.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:98) at org.hibernate.impl.SessionFactoryImpl.checkNamedQueries(SessionFactoryImpl.java:562) at org.hibernate.impl.SessionFactoryImpl.(SessionFactoryImpl.java:424) at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1385) at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:954) at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:891) at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:57) at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:48) at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:32) at net.hq.util.Db.(Db.java:7) ... 17 more

回答

-1

我想你不能在HQL中表達這個查詢。 Hibernate文檔描述的INSERT ... SELECT ...查詢一些侷限性,尤其是

select_statement can be any valid HQL select query, with the caveat that the return types must match the types expected by the insert. Currently, this is checked during query compilation rather than allowing the check to relegate to the database.

因爲你不能在查詢表達了:game有型的Game事實上,這個查詢的編譯從未成功。

嘗試改用原生SQL查詢。

+0

我明白。非常感謝。無論如何,我希望能夠解決這個問題。也許在下一個jpa發佈。 :) – mkuff 2011-01-20 19:41:46

+1

這是不正確的。我得到它的工作。也許這是因爲我在Hibernate 3.6上,而且你的東西比較老。請參閱下面的答案。 – 2013-04-23 18:32:19

2

嘗試:

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

query.setEntity("game", game);

我假設你也有一類名爲瓷磚和X,Y,tileOverlay ...是類的屬性。從Hibernate的參考文檔: 「僞語法INSERT語句是:INSERT INTO 實體名稱properties_list和 select_statement中」。

關於投功能,「中投(...爲...),其中第二個參數是一個Hibernate類型的名字」,所以它應該工作。

我didn't與實體嘗試,但它與簡單類型(字節,整數...)工作得很好。

0

我想出瞭如何從jorgegm的上述評論中做到這一點,我希望他的實際答案,因爲他的原始答案給出了一個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和它的作品就像一個魅力。