2011-09-01 61 views
1

我嘗試使用帶插件gorm-jpa 0.7.1的Grails 1.3.7來使用EclipseLink 2.2.0作爲持久性提供程序來啓用JPA持久性。在EclipseLink 2.2.0中使用Grails 1.3.7 JPA Provider

當運行應用程序,並單擊JPA註解實體離開的EclipseLink的JPQLParser控制器我得到一個「UnwantedTokenException」上:

Executing action [list] of controller [model.PersonController] caused exception: 
An exception occurred while creating a query in EntityManager: 
Exception Description: Syntax error parsing the query [select person from model.Person as person ], line 1, column 24: syntax error at [.]. 
Internal Exception: UnwantedTokenException(found=., expected 80); 
    at org.eclipse.persistence.internal.libraries.antlr.runtime.BaseRecognizer.recoverFromMismatchedToken(BaseRecognizer.java:587) 
    [...] 
    at org.eclipse.persistence.internal.jpa.parsing.jpql.JPQLParser.parse(JPQLParser.java:134) 

看來的EclipseLink與在「模型中的點有問題。人」。

如何解決這個問題?

重現該問題設置一個Grails項目如下:

grails create-app GrailsJPA 
cd GrailsJPA 
grails uninstall-plugin hibernate 
grails install-plugin gorm-jpa 
grails create-domain-class model.Person 

編輯 「的grails-app \域\型號\ Person.groovy」 如下:

package model 

import javax.persistence.*; 

@Entity 
class Person { 

    @Id 
    @GeneratedValue 
    long id; 

    @Basic 
    long version; 

    @Basic 
    String firstName 

    @Basic 
    String lastName 

    static constraints = { 
     firstName(nullable:true) 
     lastName(nullable:true) 
    } 

} 

生成控制器和視圖爲所定義的實體:

grails generate-controller model.Person 
grails generate-view model.Person 

編輯 「的grails-app \ CONF \彈簧\ resources.groovy」 如下:

beans = { 

    entityManagerFactory(org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean) { 
     beanClassLoader = ref("classLoader") 
     dataSource = ref("dataSource") 
     loadTimeWeaver = new org.springframework.instrument.classloading.SimpleLoadTimeWeaver() 
    } 

    transactionManager(org.springframework.orm.jpa.JpaTransactionManager) { 
     entityManagerFactory = entityManagerFactory 
    } 

} 

創建一個文件 「web應用程序\ WEB-INF \類\ META-INF \ persistence.xml中」 具體如下:http://www.eclipse.org/eclipselink/downloads/2.2.0和提取

<?xml version="1.0" encoding="UTF-8"?> 
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> 
    <persistence-unit name="manager" transaction-type="RESOURCE_LOCAL"> 
     <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> 
     <class>model.Person</class> 
     <properties> 
      <property name="eclipselink.ddl-generation" value="create-tables"/> 
     </properties> 
    </persistence-unit> 
</persistence> 

下載的EclipseLink 2.2.0安裝ZIP 「eclipselink.jar」 從 「的EclipseLink \ jlib \」 在ZIP到Grails項目目錄:

lib\eclipselink.jar 

現在運行Grails應用程序:

grails run-app 

瀏覽

http://localhost:8080/GrailsJPA 

現在點擊控制器 「model.PersonController」 重現上面的異常。

關於如何解決此問題的任何想法?

回答

1

我設法讓EclipseLink 2.3.0 JPA提供者以下列方式在包中使用而不是的域類。

下面我將介紹如何設置一個使用EclipseLink作爲JPA提供程序的grails應用程序,以持久化域類並在Tomcat 6 Web容器中運行應用程序。

開始通過

  • 創建一個新的Grails工程
  • 卸載默認的Hibernate插件
  • 安裝格姆-JPA插件,它允許在JPA
  • 創建一個頂級格姆類似的行爲新的領域類「Person」進行測試

    grails create-app GrailsJPA 
    cd GrailsJPA 
    grails uninstall-plugin hibernate 
    grails install-plugin gorm-jpa 
    grails create-domain-class Person 
    

提示:請問不是將域類放入包中。處理例如EclipseLink時,EclipseLink將失敗「model.Person」是因爲名字中的小圓點,但在例如「人」(與上面的帖子相比)。

編輯 「的grails-app \域\ Person.groovy」 如下:

import javax.persistence.*; 

@Entity 
class Person { 

    @Id 
    @GeneratedValue 
    long id; 

    @Basic 
    long version; 

    @Basic 
    String firstName 

    @Basic 
    String lastName 

    static constraints = { 
     firstName(nullable:true) 
     lastName(nullable:true) 
    } 

} 

生成一個控制器和定義實體的看法:

grails generate-controller Person 
grails generate-view Person 

現在我們需要修改生成的控制器略有變化,以便修改實體的所有操作(保存,編輯,更新,刪除)都封裝在一個事務中(與bug GPGORMJPA-6相比)。這是通過將整個動作封裝到「Person.withTransaction」塊中完成的。

編輯「的grails-app \控制器\ PersonController.groovy」如下:

[...] 
def save = { 
    Person.withTransaction { 
    [...original code stays in this block...] 
    } 
} 
[...] 
def edit = { 
    Person.withTransaction { 
     [...original code stays in this block...]   } 
    } 
} 
def update = { 
    Person.withTransaction { 
     [...original code stays in this block...] 
    } 
} 
def delete = { 
    Person.withTransaction { 
     [...original code stays in this block...] 
    } 
} 
[...] 

現在我們定義一個persitence單位「經理」,指定一組類爲(類「人」管理的持久性)以及哪個JPA提供者用於這些類(在我們的例子中是EclipseLink)。

創建一個文件 「web應用程序\ WEB-INF \類\ META-INF \ persistence.xml中」 如下:

<?xml version="1.0" encoding="UTF-8"?> 
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> 
    <persistence-unit name="manager" transaction-type="RESOURCE_LOCAL"> 
     <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> 
     <class>Person</class> 
     <properties> 
      <property name="eclipselink.ddl-generation" value="create-tables"/> 
     </properties> 
    </persistence-unit> 
</persistence> 

請注意:文件如果將 「目標」 目錄中被刪除項目被清理,例如當「grails clean」被明確地調用時。因此,在「目標」目錄之外備份文件是個好主意。

要的EclipseLink提供給Grails項目,下載的EclipseLink 2.3.0安裝ZIP和提取 「eclipselink.jar」 從 「的EclipseLink \ jlib \」 在ZIP爲 「LIB」 Grails項目的文件夾:

lib\eclipselink.jar 

現在我們需要確保在Web應用程序啓動時創建「entityManagerFactory」和「transactionManager」bean。這些bean將向JPA提供者提供所需的訪問權限,以管理所有的持久性。

編輯「的grails-app \的conf \彈簧\ resources.groovy」如下:

beans = { 

    entityManagerFactory(org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean) { 
     dataSource = ref("dataSource") 
     beanClassLoader = ref("classLoader") 
     loadTimeWeaver = new org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver() 
    } 

    transactionManager(org.springframework.orm.jpa.JpaTransactionManager) { 
     entityManagerFactory = entityManagerFactory 
    } 

} 

請注意,我們在指定上述聲明一個特殊的LoadTimeWeaver,這使得JPA持續性提供掛接到在運行時動態的java字節碼。在使用EclipseLink時,這很重要。如果只是使用org.springframework.instrument.classloading。SimpleLoadTimeWeaver用於測試目的,這使Web應用程序可以啓動,但在訪問JPA實體時,您將遇到例如「0不是已知實體類型」的異常,因爲持久性提供程序無法在運行時掛接到實體類的管理。

使用InstrumentationLoadTimeWeaver是有點麻煩,因爲它只會工作,如果

  • Java虛擬機執行的Web應用服務器使用的「春天代理」 Java代理,開始
  • 我們的web應用程序是通過使用名爲「TomcatInstrumentableClassLoader的」

爲了實現這個特殊的類加載器的Tomcat服務器,首先下載加載spring-agent-2.5.6.SEC02.jarspring-instrument-tomcat-3.0.5.RELEASE.jar

假設您已在目錄%CATALINA_HOME%中安裝了Tomcat服務器。

  • 複製下載的jar文件 「彈簧代理2.5.6.SEC02.jar」 和 「彈簧儀器的tomcat-3.0.5.RELEASE.jar」 到%CATALINA_HOME%\ lib中

現在我們修改例如使用的「%CATALINA_HOME%\ bin \ catalina.bat」 Tomcat的啓動和停止腳本以確保執行Tomcat的JVM與「spring-agent」java代理一起運行。

以下內容添加到「%CATALINA_HOME%\ BIN \ catalina.bat中」一節「執行請求的命令」所有的回聲後:

if exist "%CATALINA_HOME%\lib\spring-agent-2.5.6.SEC02.jar" set JAVA_OPTS=%JAVA_OPTS% -javaagent:%CATALINA_HOME%\lib\spring-agent-2.5.6.SEC02.jar 

當Tomcat啓動時,該腳本將現在檢查「spring-agent-2.5.6.SEC02.jar」位於lib目錄下,如果是這種情況,它會將它作爲java代理添加到JAVA_OPTS中,在啓動Tomcat時用作命令行參數給JVM 。

要啓用「Tomcat的」作爲我們的web應用程序的類加載器,我們的文件「web應用程序\ META-INF \ context.xml的」添加到我們的Grails項目,具有以下內容:

<?xml version="1.0" encoding="UTF-8"?> 
<Context> 
    <Loader loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"/> 
</Context> 

請注意,「context.xml」中的標籤區分大小寫。所以不要試圖改變< C ontext > to < c ontext >(或類似的事情) - 這將失敗!

在我們打包並部署我們的Web應用程序之前,我們定義了要用於持久性的數據源。爲了測試,我們只需定義一個HSQLDB內存數據庫。

編輯 「的grails-app \的conf \ DataSource.groovy中的」 如下:

[...] 
development { 
    dataSource { 
     dbCreate = "create-drop" 
     url = "jdbc:hsqldb:mem:testDB" 
    } 
} 
test { 
    dataSource { 
     dbCreate = "create-drop" 
     url = "jdbc:hsqldb:mem:testDb" 
    } 
} 
production { 
    dataSource { 
     dbCreate = "create-drop" 
     url = "jdbc:hsqldb:mem:testDB" 
    } 
} 
[...] 

現在我們已經準備好使用的是創建我們的Web應用程序的WAR檔案:

grails war 

的WAR將被放置在我們項目的「目標」目錄中。

在 「%CATALINA_HOME%\ web應用」

  • 創建一個目錄 「GrailsJPA」
  • 提取創建的WAR歸檔的所有內容複製到該目錄

請注意:不要將WAR放在「%CATALINA_HOME%\ webapps」中,並希望它在Tomcat啓動時部署。這將失敗!

現在使用腳本

"%CATALINA_HOME%\bin\startup.bat" 

Tomcat是後以及運行啓動Tomcat服務器,使用瀏覽器瀏覽到

http://localhost:8080/GrailsJPA 

現在點擊控制器「PersonController」創建,更新,使用EclipseLink JPA提供程序通過JPA列出並刪除人員實體。

但是使用包內部的域類仍然會失敗,並且上述帖子中提到了異常。這個問題仍然沒有解決。

下載鏈接

  • 的Grails 1.3.7

    http://grails.org/Download 
    
  • 的EclipseLink 2.3.0

    http://www.eclipse.org/eclipselink/downloads/2.3.0 
    
  • 的Tomcat 6

    http://tomcat.apache.org/download-60.cgi 
    
  • 彈簧儀器Tomcat的3.0.5.RELEASE.jar

    http://mvnrepository.com/artifact/org.springframework/spring-instrument-tomcat 
    
  • 彈簧劑2.5.6.SEC02.jar

    http://mvnrepository.com/artifact/org.springframework/spring-agent