简体   繁体   English

从Tapestry持久化数据并休眠

[英]Persist Data from Tapestry with Hibernate Issue

I've read many of the other examples, but cannot seem to persist my data with hibernate. 我已经阅读了许多其他示例,但是似乎无法使用休眠方式保留我的数据。

I have code here that creates the objects: 我这里有创建对象的代码:

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;
    }
}

Then, I have the object class itself: 然后,我有了对象类本身:

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;
    }

And finally my config page: 最后是我的配置页面:

<!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>

When I run everything, this is what I get spit back from the process: 当我运行所有内容时,这就是从过程中吐出来的内容:

 [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

It looks like above the object is properly created, but I am really struggling on the persistence side. 看起来上面的对象是正确创建的,但是我在持久性方面确实很挣扎。 Any help would be greatly appreciated. 任何帮助将不胜感激。

Okay, unfortunately, my post must not have gotten enough attention here, but I have done tons of research around this area now and thought I would share what I found. 好的,很遗憾,我的帖子在这里可能没有引起足够的重视,但是我现在在这一领域进行了大量研究,并认为我会分享我的发现。

First, I changed to SQL instead of using hibernates native database. 首先,我改为使用SQL,而不使用休眠的本机数据库。 This sped things up 10 fold. 这加快了十倍。 I understand it may not be the best solution for all applications, but for smaller or non-essential applications, its the easiest. 我知道这可能不是所有应用程序的最佳解决方案,但是对于较小或非必需的应用程序来说,这是最简单的。

Below my Hibernate config file: 在我的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>

Note that the port will usually be 3306 if you are running locally. 请注意,如果您在本地运行,则端口通常为3306。 If that is your goal, make sure to set up your MySQL database as such (and look for the port it will be listening on). 如果这是您的目标,请确保以此方式设置您的MySQL数据库(并查找它将监听的端口)。 You will have to install the JDBC jar. 您将必须安装JDBC jar。 The easiest way is if you have homebrew. 最简单的方法是自制。 Note it is a two step installation: https://github.com/gbeine/homebrew-java 注意这是一个两步安装: https : //github.com/gbeine/homebrew-java

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

Below your main configuration, you have to tell Hibernate what your classes are. 在主要配置下面,您必须告诉Hibernate什么是类。 This is the mapping class section. 这是映射类部分。 I have seen a million implementations of this with package mapping, etc. Again, for a simple app, this is easiest. 我已经看到了用软件包映射等实现的一百万个实现。同样,对于一个简单的应用程序,这是最简单的。

Once you have mapped your class in the Hibernate config file, go back to your .java class to structure it in a way Hibernate will associate it properly with your MySQL tables. 在将类映射到Hibernate配置文件中之后,请返回.java类,以Hibernate将其正确地与MySQL表关联的方式来构造它。

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

When you declare each variable, you need to assure that you have the correct data type. 声明每个变量时,需要确保您具有正确的数据类型。 You can see here that I have incorrectly (on purpose) declared progress an int when it should be a double. 您可以在此处看到我错误地(故意地)将progress声明为int,而它应该是double。

Note that I have declared these variables as columns and the name of the column in the DB. 请注意,我已将这些变量声明为列,并在数据库中声明了该列的名称。 This is essential and you will have many headaches without this. 这是必不可少的,否则,您会头疼很多。

Finally, when you go to save your data, I found there are tons of stackoverflow descriptions for forms, but none for backend initiated DB saves. 最后,当您去保存数据时,我发现有很多关于表单的stackoverflow描述,但是没有关于后端启动的DB保存的描述。 So, I have included that code below, too: 因此,我也将以下代码包括在内:

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

}

Basically, you have to start a session with @Inject. 基本上,您必须使用@Inject开始会话。 Then, as this is a WS that processes URL parameters, I use @SetupRender to start the method upon page render. 然后,因为这是一个处理URL参数的WS,所以我使用@SetupRender在页面渲染时启动该方法。 Many times, people put the @CommitAfter after this entire method with an OnSuccess method, but for java initiated sessions, this does not work. 很多时候,人们将@CommitAfter放在带有OnSuccess方法的整个方法之后,但是对于Java启动的会话,这是行不通的。 So for these, I put it directly after the SetupRender to make sure that all the session saves/edits/deletes I perform during the method are committed afterwards. 因此,对于这些,我将其直接放在SetupRender之后,以确保之后在方法中执行的所有会话保存/编辑/删除操作都已提交。 Without this, your program will quietly fail. 没有这个,您的程序将安静地失败。 Nothing will jump out at you and your data will not be saved. 没有任何东西会冲您,您的数据将不会被保存。

I apologize as I am a bit of a newb at development so I may not have described everything here optimally, but hope it can help someone down the road. 我很抱歉,因为我对开发尚不满意,所以我可能在这里没有对所有内容进行最佳描述,但希望它对以后的工作有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM