我使用以下内容:
此外,我是Glassfish,DerbyDB,JPA,EcliseLink和Vaadin的新手:-) 如果我错了,请纠正我!
首先:
请注意,有几个examples using the Application
class,但由于这是关于Vaadin 6,它不适合我。
我希望使用JPA在Derby DB中保留实体Member
,但我现在已经困难了两天了。我尝试做的是注入一个无状态EJB MemberManagerBean
,它有一个EntityManager
来管理实体Member
,在Vaadin UI
的任何地方使用它CustomComponent
创建布局。
package de.ves.beans.entities;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Version;
@Entity
public class Member implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
protected Long id;
@Version
@Column(name = "OPTLOCK")
private Long version;
protected String name;
public Member(){}
// getters and setters ...
}
package de.ves.beans.mgm;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import de.ves.beans.entities.Member;
@Stateless
public class MemberManagerBean implements MemberManagerLocal {
@PersistenceContext
protected EntityManager entityManager;
@Override
public Member getMember(Long id) {
return entityManager.find(Member.class, id);
}
@Override
public Member saveMember(Member member) {
if (member.getId() == null){
entityManager.persist(member);
}else{
entityManager.merge(member);
}
return member;
}
}
package de.ves.beans.mgm;
import javax.ejb.Local;
import javax.ejb.TransactionAttribute;
import de.ves.beans.entities.Member;
@TransactionAttribute
@Local
public interface MemberManagerLocal {
public Member getMember(Long id);
public Member saveMember(Member member);
}
package de.ves.ui;
import javax.servlet.annotation.WebServlet;
import com.vaadin.annotations.Theme;
import com.vaadin.annotations.Title;
import com.vaadin.annotations.VaadinServletConfiguration;
import com.vaadin.navigator.Navigator;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinServlet;
import com.vaadin.ui.UI;
import de.ves.beans.mgm.MemberManagerBean;
import de.ves.club.Friends;
import de.ves.club.Members;
import de.ves.club.News;
import de.ves.contact.About;
import de.ves.home.Home;
import de.ves.media.Pics;
import de.ves.media.Videos;
@SuppressWarnings("serial")
@Theme("ves")
public class VesUI extends UI {
private Navigator navigator;
@WebServlet(value = "/*", asyncSupported = true)
@VaadinServletConfiguration(productionMode = false, ui = VesUI.class)
public static class Servlet extends VaadinServlet {
}
@Override
protected void init(VaadinRequest request) {
navigator = new Navigator(this, this);
// Home
MainLayout main = new MainLayout();
main.setMiddle(new Home());
navigator.addView(Home.PATH, main);
// ErrorView
navigator.setErrorView(main);
// Subpages
main = new MainLayout();
main.setMiddle(new Members());
navigator.addView(Members.PATH, main);
// ...
}
}
package de.ves.club;
import com.vaadin.addon.jpacontainer.JPAContainer;
import com.vaadin.addon.jpacontainer.JPAContainerFactory;
import com.vaadin.annotations.AutoGenerated;
import com.vaadin.server.FileResource;
import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.Label;
import com.vaadin.ui.Panel;
import com.vaadin.ui.VerticalLayout;
import de.ves.beans.entities.Member;
@SuppressWarnings("serial")
public class Members extends CustomComponent {
// Components and stuff...
public Members() {
buildMainLayout();
setCompositionRoot(mainLayout);
pnl_root.setSizeFull();
// Several inits...
// This is where I want to read/write from/into the DB.
// This is not possible since I can't access the
// MemberManagerBean. The following code shows my approach
// concering with a JPAContainer.
JPAContainer<Member> members = JPAContainerFactory.make(Member.class, "vesPersistence");
Member m = new Member();
members.addEntity(m);
}
@AutoGenerated
private VerticalLayout buildMainLayout() {
// ...
}
// ...
}
<?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_2_0.xsd"
version="2.0">
<persistence-unit name="vesPersistence">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>de.ves.beans.entities.Member</class>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="eclipselink.target-database" value="Derby" />
<property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver" />
<property name="javax.persistence.jdbc.url" value="jdbc:derby://localhost:1527/ves;create=true" />
<property name="javax.persistence.jdbc.user" value="admin" />
<property name="javax.persistence.jdbc.password" value="..." />
<property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
<property name="eclipselink.logging.level" value="INFO" />
</properties>
</persistence-unit>
</persistence>
我的第一种方法是在CustomComponent
...
@EJB
private MemberManagerBean memberManager;
...但这导致NullPointerException
。
我读到注射仅适用于Servlet
。 (这是对的吗?)
现在,问题在于,与普通DWP不同,在Vaadin项目中(在MY Vaadin项目中)只有一个Servlet
,这是UI
中的静态类。应用程序内部的导航通过Navigator
进行,其他Servlets
是不必要的。虽然注入静态Servlet
对我来说是错误的,但我尝试了这种方法。再次,NullPointerException
。
第三种方法:按照on vaadin.com使用JPAContainer
。这几乎正常,但触发ServletException
。请参阅Members
类中的代码。
它触发了以下内容:
javax.servlet.ServletException:com.vaadin.server.ServiceException:java.lang.IllegalStateException: 异常描述:使用JTA时无法使用EntityTransaction。
我无法解释为什么会这样。
我的最后一种方法是关注this forum thread,但也导致了NullPointerException
。此外,我真的不想使用它,因为它似乎是一种解决方法。
我很想使用JPAContainer
,但在Vaadin中使用JPA的常用方法确实会有所帮助。
就是这样。能帮到我吗:-)在此先感谢您的帮助!