我使用以下内容:
- Eclipse Java EE 朱诺
- GlassFish 3.1.2,
- 德比数据库,
- JPA,
- EclipseLink 和
- 瓦丁 7.1.1。
此外,我是 Glassfish、DerbyDB、JPA、EcliseLink 和 Vaadin 的新手 :-) 所以如果我错了,请纠正我!
首先:请注意,有几个使用该类的示例Application
,但由于这是关于 Vaadin 6,它不适合我。
我想Member
使用 JPA 在 Derby DB 中持久化一个实体,但是我现在两天都在做这件事。我尝试做的是在 Vaadin 的任何地方注入一个无状态的 EJB MemberManagerBean
,它有一个EntityManager
来管理实体,以便在一个内部使用它来创建一个布局。Member
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>
我的第一种方法是将 EJB 注入CustomComponent
...
@EJB
private MemberManagerBean memberManager;
...但这会导致NullPointerException
.
我读到注入仅在Servlet
. (这是正确的吗?)
现在,问题在于,与常见的 DWP 不同,在 Vaadin 项目(在 MY Vaadin 项目中)只有Servlet
一个UI
. 应用程序内部的导航是通过 a 进行的Navigator
,其他Servlets
的都是不必要的。尽管静态注射Servlet
对我来说是错误的,但我尝试了这种方法。再次,NullPointerException
.
第三种方法:使用 a JPAContainer
,如vaadin.com 上所述。这几乎可以正常工作,但触发了ServletException
. 请参阅类中的代码Members
。
它触发了以下内容:
javax.servlet.ServletException: com.vaadin.server.ServiceException: java.lang.IllegalStateException: 异常描述:在使用 JTA 时无法使用 EntityTransaction。
我无法解释为什么会出现这种情况。
我最后的方法是关注这个论坛帖子,但它也导致了一个NullPointerException
. 此外,我真的不想使用它,因为它似乎是一种解决方法。
我很想使用JPAContainer
,但在 Vaadin 中使用 JPA 的一种常见的常规方式确实会有所帮助。
而已。你能帮我吗 :-) 在此先感谢您的帮助!