使用 Hibernate 问题从 Tapestry 持久化数据

Persist Data from Tapestry with Hibernate Issue

我已经阅读了许多其他示例,但似乎无法使用休眠来保存我的数据。

我这里有创建对象的代码:

package com.example.leaderboardApp.pages;

import com.example.leaderboardApp.utility.Competitor;
import org.apache.tapestry5.annotations.RequestParameter;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.annotations.SetupRender;
import org.apache.tapestry5.annotations.ActivationRequestParameter;
import org.apache.tapestry5.hibernate.annotations.CommitAfter;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.hibernate.Session;



public class Ws {
    @ActivationRequestParameter("hipchat_id") private int hipchat_id;
    @ActivationRequestParameter("name") private String name;
    @ActivationRequestParameter("dips") private int dips;

    @Property
    private Competitor competitor;

    @Inject
    private Session session;

    @SetupRender
    void appUpdate() {
        competitor = new Competitor(hipchat_id, name);
        competitor.addReps(dips);
        System.out.println(competitor);
    }

    @CommitAfter
    Object onSuccess() {
        session.persist(competitor);
        return hipchat_id;
    }
}

然后,我有对象 class 本身:

package com.example.leaderboardApp.utility;

import java.util.ArrayList;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

import org.apache.tapestry5.beaneditor.NonVisual;
import org.apache.tapestry5.beaneditor.Validate;

import com.example.leaderboardApp.pages.Index;
import org.apache.tapestry5.annotations.InjectPage;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.hibernate.annotations.CommitAfter;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.hibernate.Session;


@Entity()
public class Competitor {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @NonVisual
    public int hipchat_id;

    @Validate("required")
    private String name;

    private int score;

    private int goal = 14000;

    private int progress = score/goal;

    public Competitor(int hipchat_id, String name) {
        this.hipchat_id = hipchat_id;
        this.name = name;
    }


    public String getName() {
        return this.name;
    }

    public void addReps(int repetitions) {
        this.score += repetitions;
    }

最后是我的配置页面:

<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property>
        <property name="hibernate.connection.url">jdbc:hsqldb:./target/work/leaderboardApp;shutdown=true</property>
        <property name="hibernate.dialect">org.hibernate.dialect.HSQLDialect</property>
        <property name="hibernate.connection.username"></property>
        <property name="hibernate.connection.password"></property>
        <property name="hbm2ddl.auto">update</property>
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.format_sql">true</property>
        <mapping package="com.example.leaderboardApp.utility.Competitor" />
    </session-factory>
</hibernate-configuration>

当我运行一切的时候,这就是我从过程中得到的吐槽:

 [INFO] Started SelectChannelConnector@0.0.0.0:8080
[INFO] Started Jetty Server
[INFO] common.Version Hibernate Commons Annotations 3.2.0.Final
[INFO] cfg.Environment Hibernate 3.6.0.Final
[INFO] cfg.Environment hibernate.properties not found
[INFO] cfg.Environment Bytecode provider name : javassist
[INFO] cfg.Environment using JDK 1.4 java.sql.Timestamp handling
[INFO] cfg.Configuration configuring from resource: /hibernate.cfg.xml
[INFO] cfg.Configuration Configuration resource: /hibernate.cfg.xml
[WARN] util.DTDEntityResolver recognized obsolete hibernate namespace http://hibernate.sourceforge.net/. Use namespace http://www.hibernate.org/dtd/ instead. Refer to Hibernate 3.6 Migration Guide!
[INFO] cfg.Configuration Mapping package com.example.leaderboardApp.utility.Competitor
[WARN] cfg.AnnotationBinder Package not found or wo package-info.java: com.example.leaderboardApp.utility.Competitor
[INFO] cfg.Configuration Configured SessionFactory: null
[INFO] cfg.Configuration Mapping package com.example.leaderboardApp.entities
[WARN] cfg.AnnotationBinder Package not found or wo package-info.java: com.example.leaderboardApp.entities
[INFO] cfg.Configuration Hibernate Validator not found: ignoring
[INFO] search.HibernateSearchEventListenerRegister Unable to find org.hibernate.search.event.FullTextIndexEventListener on the classpath. Hibernate Search is not enabled.
[INFO] connection.DriverManagerConnectionProvider Using Hibernate built-in connection pool (not for production use!)
[INFO] connection.DriverManagerConnectionProvider Hibernate connection pool size: 20
[INFO] connection.DriverManagerConnectionProvider autocommit mode: false
[INFO] connection.DriverManagerConnectionProvider using driver: org.hsqldb.jdbcDriver at URL: jdbc:hsqldb:./target/work/leaderboardApp;shutdown=true
[INFO] connection.DriverManagerConnectionProvider connection properties: {user=, password=****}
[INFO] cfg.SettingsFactory Database ->
       name : HSQL Database Engine
    version : 2.3.2
      major : 2
      minor : 3
[INFO] cfg.SettingsFactory Driver ->
       name : HSQL Database Engine Driver
    version : 2.3.2
      major : 2
      minor : 3
[INFO] dialect.Dialect Using dialect: org.hibernate.dialect.HSQLDialect
[INFO] transaction.TransactionFactoryFactory Using default transaction strategy (direct JDBC transactions)
[INFO] transaction.TransactionManagerLookupFactory No TransactionManagerLookup configured (in JTA environment, use of read-write or transactional second-level cache is not recommended)
[INFO] cfg.SettingsFactory Automatic flush during beforeCompletion(): disabled
[INFO] cfg.SettingsFactory Automatic session close at end of transaction: disabled
[INFO] cfg.SettingsFactory JDBC batch size: 15
[INFO] cfg.SettingsFactory JDBC batch updates for versioned data: disabled
[INFO] cfg.SettingsFactory Scrollable result sets: enabled
[INFO] cfg.SettingsFactory JDBC3 getGeneratedKeys(): enabled
[INFO] cfg.SettingsFactory Connection release mode: auto
[INFO] cfg.SettingsFactory Default batch fetch size: 1
[INFO] cfg.SettingsFactory Generate SQL with comments: disabled
[INFO] cfg.SettingsFactory Order SQL updates by primary key: disabled
[INFO] cfg.SettingsFactory Order SQL inserts for batching: disabled
[INFO] cfg.SettingsFactory Query translator: org.hibernate.hql.ast.ASTQueryTranslatorFactory
[INFO] ast.ASTQueryTranslatorFactory Using ASTQueryTranslatorFactory
[INFO] cfg.SettingsFactory Query language substitutions: {}
[INFO] cfg.SettingsFactory JPA-QL strict compliance: disabled
[INFO] cfg.SettingsFactory Second-level cache: enabled
[INFO] cfg.SettingsFactory Query cache: disabled
[INFO] cfg.SettingsFactory Cache region factory : org.hibernate.cache.impl.NoCachingRegionFactory
[INFO] cfg.SettingsFactory Optimize cache for minimal puts: disabled
[INFO] cfg.SettingsFactory Structured second-level cache entries: disabled
[INFO] cfg.SettingsFactory Echoing all SQL to stdout
[INFO] cfg.SettingsFactory Statistics: disabled
[INFO] cfg.SettingsFactory Deleted entity synthetic identifier rollback: disabled
[INFO] cfg.SettingsFactory Default entity-mode: pojo
[INFO] cfg.SettingsFactory Named query checking : enabled
[INFO] cfg.SettingsFactory Check Nullability in Core (should be disabled when Bean Validation is on): enabled
[INFO] impl.SessionFactoryImpl building session factory
[INFO] impl.SessionFactoryObjectFactory Not binding factory to JNDI, no JNDI name configured
[INFO] hbm2ddl.SchemaUpdate Running hbm2ddl schema update
[INFO] hbm2ddl.SchemaUpdate fetching database metadata
[INFO] hbm2ddl.SchemaUpdate updating schema
[INFO] hbm2ddl.SchemaUpdate schema update complete
[INFO] HibernateCoreModule.HibernateSessionSource Hibernate startup: 122 ms to configure, 371 ms overall.
[INFO] HibernateCoreModule.HibernateSessionSource Configured Hibernate entities: (none)
com.example.leaderboardApp.utility.Competitor@3d03f309
[INFO] AppModule.TimingFilter Request time: 954 ms

看起来上面的对象已正确创建,但我真的在持久性方面苦苦挣扎。任何帮助将不胜感激。

好吧,不幸的是,我的 post 在这里没有得到足够的关注,但我现在已经围绕这个领域进行了大量研究,我想我会分享我的发现。

首先,我改为 SQL 而不是使用 hibernates 本机数据库。这将速度提高了 10 倍。我知道它可能不是所有应用程序的最佳解决方案,但对于较小或非必要的应用程序,它是最简单的。

在我的 Hibernate 配置文件下面:

<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/leaderboardApp</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password"></property>
        <property name="hbm2ddl.auto">update</property>
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.format_sql">true</property>
        <mapping class="com.example.leaderboardApp.utility.Competitor"/>
        <mapping class="com.example.leaderboardApp.utility.Record"/>
    </session-factory>
</hibernate-configuration>

请注意,如果您在本地 运行,端口通常为 3306。如果那是您的目标,请确保如此设置您的 MySQL 数据库(并查找它将监听的端口)。您将必须安装 JDBC jar。最简单的方法是如果你有自制软件。请注意,这是一个两步安装:https://github.com/gbeine/homebrew-java

brew tap gbeine/homebrew-java
brew install mysql-connector-java

在您的主要配置之下,您必须告诉 Hibernate 您的 classes 是什么。这是映射 class 部分。我已经通过包映射等看到了上百万个实现。同样,对于一个简单的应用程序,这是最简单的。

在 Hibernate 配置文件中映射 class 后,返回到您的 .java class 以 Hibernate 将其与您的 [ 正确关联的方式构建它=40=] 表。

@Entity
@Table(name="competitors")
public class Competitor {
    @Id
    @Column(name="hipchat_id", unique=true, nullable=false)
    public int hipchat_id;

    @Column(name="name")
    @Validate("required")
    private String name;

    @Column(name="score")
    private int score;

    @Column(name="goal")
    private int goal = 14000;

    @Column(name="progress")
    private int progress = score/goal;

当您声明每个变量时,您需要确保您拥有正确的数据类型。你可以在这里看到我错误地(故意)将 progress 声明为 int 而它应该是 double。

请注意,我已将这些变量声明为数据库中的列和列的名称。这是必不可少的,没有它你会很头疼。

最后,当您去保存数据时,我发现有大量关于表单的 Whosebug 描述,但是 none 对于后端启动的数据库保存。因此,我也在下面包含了该代码:

public class Ws {
    @ActivationRequestParameter("hipchat_id") private int hipchat_id;
    @ActivationRequestParameter("name") private String name;
    @ActivationRequestParameter("dips") private int dips;

    @Property
    private Competitor competitor;

    @Inject
    private Session session;

    @SetupRender
    @CommitAfter
    void appUpdate() {
        session.saveOrUpdate(new Competitor(hipchat_id, name, dips));
        session.save(new Record(hipchat_id, dips));
    }

}

基本上,您必须使用@Inject 启动会话。然后,因为这是一个处理 URL 参数的 WS,所以我使用 @SetupRender 在页面呈现时启动该方法。很多时候,人们将 @CommitAfter 放在带有 OnSuccess 方法的整个方法之后,但是对于 java 启动的会话,这是行不通的。因此,对于这些,我将它直接放在 SetupRender 之后,以确保我在该方法期间执行的所有会话 saves/edits/deletes 都在之后提交。没有这个,你的程序就会悄悄地失败。什么都不会跳到你身上,你的数据也不会被保存。

我很抱歉,因为我在开发方面有点新手,所以我可能没有对这里的所有内容进行最佳描述,但希望它能对以后的人有所帮助。