JPA(Java Persistence API)是JSR(Java Specification Requests)的一部分,定义了一系列对象持久化的标准,目前实现这一规范的产品有Hibernate、TopLink等。
下面的示例程序是在jboss quickStart的基础上修改而来的
1、实体Bean:Member类
1 package org.jboss.as.quickstart.hibernate4.model;
2
3 import java.io.Serializable;
4
5 import javax.persistence.Column;
6 import javax.persistence.Entity;
7 import javax.persistence.GeneratedValue;
8 import javax.persistence.GenerationType;
9 import javax.persistence.Id;
10 import javax.persistence.SequenceGenerator;
11 import javax.persistence.Table;
12 import javax.validation.constraints.Digits;
13 import javax.validation.constraints.NotNull;
14 import javax.validation.constraints.Pattern;
15 import javax.validation.constraints.Size;
16 import javax.xml.bind.annotation.XmlRootElement;
17 import org.hibernate.validator.constraints.Email;
18 import org.hibernate.validator.constraints.NotEmpty;
19
20 @Entity
21 @XmlRootElement
22 @Table(name = "MemberHibernate4Demo")
23 public class Member implements Serializable {
24
25 private static final long serialVersionUID = 3862416351900991824L;
26
27 @Id
28 @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "MEMBER_ID_GENERATOR")
29 @SequenceGenerator(name = "MEMBER_ID_GENERATOR", sequenceName = "SEQ_MEMBER", allocationSize = 1)
30 private Long id;
31
32 @NotNull
33 @Size(min = 1, max = 25)
34 @Pattern(regexp = "[A-Za-z ]*", message = "must contain only letters and spaces")
35 private String name;
36
37 @NotNull
38 @NotEmpty
39 @Email
40 private String email;
41
42 @NotNull
43 @Size(min = 9, max = 12)
44 @Digits(fraction = 0, integer = 12)
45 @Column(name = "phone_number")
46 private String phoneNumber;
47
48 private String address;
49
50 public Long getId() {
51 return id;
52 }
53
54 public void setId(Long id) {
55 this.id = id;
56 }
57
58 public String getName() {
59 return name;
60 }
61
62 public void setName(String name) {
63 this.name = name;
64 }
65
66 public String getEmail() {
67 return email;
68 }
69
70 public void setEmail(String email) {
71 this.email = email;
72 }
73
74 public String getPhoneNumber() {
75 return phoneNumber;
76 }
77
78 public void setPhoneNumber(String phoneNumber) {
79 this.phoneNumber = phoneNumber;
80 }
81
82 public String getAddress() {
83 return address;
84 }
85
86 public void setAddress(String address) {
87 this.address = address;
88 }
89
90 public String toString() {
91
92 return "id:" + id + ",name:" + name + ",email:" + email
93 + ",phoneNumber:" + phoneNumber + ",address:" + address;
94 }
95 }
注意:私有成员id上的注解@SequenceGenerator、@GeneratedValue演示Oracle中序列(Sequence)的用法。
2、服务接口 MemberService
1 package org.jboss.as.quickstart.hibernate4.service;
2
3 import java.util.List;
4
5 import org.jboss.as.quickstart.hibernate4.model.Member;
6
7 public interface MemberService {
8
9 void addMember(Member member) throws Exception;
10
11 void updateMember(Member member) throws Exception;
12
13 void deleteMember(long id) throws Exception;
14
15 Member findMember(long id) throws Exception;
16
17 List<Member> getMembers() throws Exception;
18
19 }
3、服务实现 MemberServiceImpl
1 package org.jboss.as.quickstart.hibernate4.service;
2
3 import java.util.logging.Logger;
4 import java.util.List;
5 import javax.ejb.Stateless;
6 import javax.enterprise.event.Event;
7 import javax.inject.Inject;
8 import javax.persistence.EntityManager;
9 import javax.persistence.PersistenceContext;
10 import org.jboss.as.quickstart.hibernate4.model.Member;
11
12 @Stateless
13 public class MemberServiceImpl implements MemberService {
14
15 @PersistenceContext
16 private EntityManager em;
17
18 @Inject
19 private Logger log;
20
21 @Inject
22 private Event<Member> memberEventSrc;
23
24 @Override
25 public void addMember(Member member) throws Exception {
26 log.info("addMember => " + member.toString());
27 member.setId(null);
28 em.persist(member);
29 memberEventSrc.fire(member);
30 }
31
32 @Override
33 public void updateMember(Member member) throws Exception {
34 log.info("updateMember => " + member.getName());
35 if (member.getId() > 0) {
36 Member updateObj = findMember(member.getId());
37 updateObj.setAddress(member.getAddress());
38 updateObj.setEmail(member.getEmail());
39 updateObj.setName(member.getName());
40 updateObj.setPhoneNumber(member.getPhoneNumber());
41 em.merge(updateObj);
42 memberEventSrc.fire(updateObj);
43 }
44
45 }
46
47 @Override
48 public void deleteMember(long id) throws Exception {
49 log.info("deleteMember => " + id);
50 Member member = findMember(id);
51 em.remove(member);
52 memberEventSrc.fire(member);
53
54 }
55
56 @Override
57 public List<Member> getMembers() throws Exception {
58 @SuppressWarnings("unchecked")
59 List<Member> members = em.createQuery("from Member").getResultList();
60 return members;
61
62 }
63
64 @Override
65 public Member findMember(long id) throws Exception {
66 log.info("findMember => " + id);
67 return em.find(Member.class, id);
68 }
69
70 }
注意:此外大量使用了CDI来实现对象的依赖注入,@PersistenceContext 用于在EJB容器中自动注入"实体管理器"(所以类上要使用@Stateless表示,这是一个无状态的EJB),上面这段代码演示了数据的基础CRUD(Create、Retrieve、Update、Delete)操作,另外为了配合CDI的@Inject注入,还需要一些@Produces的辅助工具类。(对CDI不熟悉的,可以先看看这里 http://www.cnblogs.com/yjmyzz/p/j2ee-cdi-inject.html )
4、辅助类 Resouces
1 package org.jboss.as.quickstart.hibernate4.util;
2
3 import java.util.Map;
4 import java.util.logging.Logger;
5 import javax.enterprise.context.RequestScoped;
6 import javax.enterprise.inject.Produces;
7 import javax.enterprise.inject.spi.InjectionPoint;
8 import javax.faces.context.FacesContext;
9
10 public class Resources {
11
12 @Produces
13 public Logger produceLog(InjectionPoint injectionPoint) {
14 return Logger.getLogger(injectionPoint.getMember().getDeclaringClass()
15 .getName());
16 }
17
18 @Produces
19 @RequestScoped
20 public FacesContext produceFacesContext() {
21 return FacesContext.getCurrentInstance();
22 }
23
24 @Produces
25 @RequestScoped
26 public Map<String, String> getRequestParameterMap(){
27 return FacesContext.getCurrentInstance().getExternalContext()
28 .getRequestParameterMap();
29 }
30
31
32 }
注:该类主要用@Produces提供了CDI注入对象的实例化方法。
5、web层的Controller:MemberController
1 package org.jboss.as.quickstart.hibernate4.controller;
2
3 import java.util.List;
4 import java.util.Map;
5
6 import javax.annotation.PostConstruct;
7 import javax.enterprise.inject.Model;
8 import javax.enterprise.inject.Produces;
9 import javax.faces.application.FacesMessage;
10 import javax.faces.context.FacesContext;
11 import javax.inject.Inject;
12 import javax.inject.Named;
13
14 import org.jboss.as.quickstart.hibernate4.model.Member;
15 import org.jboss.as.quickstart.hibernate4.service.MemberService;
16
17 @Model
18 public class MemberController {
19
20 @Inject
21 MemberService service;
22
23 @Inject
24 private FacesContext facesContext;
25
26 @Inject
27 private Map<String, String> requestMap;
28
29 private Member newMember;
30
31 @Produces
32 @Named
33 public Member getNewMember() {
34 return newMember;
35 }
36
37 @Produces
38 @Named
39 public List<Member> getMembers() {
40 List<Member> members = null;
41 try {
42 members = service.getMembers();
43
44 } catch (Exception e) {
45 String errorMessage = getRootErrorMessage(e);
46 facesContext.addMessage(null, new FacesMessage(
47 FacesMessage.SEVERITY_ERROR, errorMessage,
48 "Delete unsuccessful"));
49 }
50 return members;
51 }
52
53 public void deleteMemberById() {
54 try {
55 String id = requestMap.get("id");
56 service.deleteMember(Long.parseLong(id));
57
58 } catch (Exception e) {
59 String errorMessage = getRootErrorMessage(e);
60 facesContext.addMessage(null, new FacesMessage(
61 FacesMessage.SEVERITY_ERROR, errorMessage,
62 "Delete unsuccessful"));
63 }
64
65 }
66
67 public void findMemberById() {
68 try {
69 String id = requestMap.get("id");
70 newMember = service.findMember(Long.parseLong(id));
71 } catch (Exception e) {
72 String errorMessage = getRootErrorMessage(e);
73 facesContext.addMessage(null, new FacesMessage(
74 FacesMessage.SEVERITY_ERROR, errorMessage,
75 "Find Member unsuccessful"));
76 }
77
78 }
79
80 public void register() {
81 try {
82 if (newMember.getId() > 0) {
83 service.updateMember(newMember);
84 facesContext.addMessage(null, new FacesMessage(
85 FacesMessage.SEVERITY_INFO, "Updated!",
86 "Update successful"));
87 } else {
88 service.addMember(newMember);
89 facesContext.addMessage(null, new FacesMessage(
90 FacesMessage.SEVERITY_INFO, "Registered!",
91 "Registration successful"));
92 }
93 initNewMember();
94 } catch (Exception e) {
95 String errorMessage = getRootErrorMessage(e);
96 facesContext.addMessage(null, new FacesMessage(
97 FacesMessage.SEVERITY_ERROR, errorMessage,
98 "Save unsuccessful"));
99 }
100 }
101
102 @PostConstruct
103 public void initNewMember() {
104 newMember = new Member();
105 }
106
107 private String getRootErrorMessage(Exception e) {
108 String errorMessage = "Registration failed. See server log for more information";
109 if (e == null) {
110 return errorMessage;
111 }
112
113 Throwable t = e;
114 while (t != null) {
115
116 errorMessage = t.getLocalizedMessage();
117 t = t.getCause();
118 }
119
120 return errorMessage;
121 }
122
123 }
6、UI界面index.xhtml
1 <?xml version="1.0" encoding="UTF-8"?>
2 <ui:composition xmlns="http://www.w3.org/1999/xhtml"
3 xmlns:ui="http://java.sun.com/jsf/facelets"
4 xmlns:f="http://java.sun.com/jsf/core"
5 xmlns:h="http://java.sun.com/jsf/html"
6 template="/WEB-INF/templates/default.xhtml">
7 <ui:define name="content">
8 <h:form id="reg">
9 <h2>Member Registration</h2>
10
11 <h:panelGrid columns="3" width="100%" columnClasses="titleCell">
12 <h:inputHidden value="#{newMember.id}" id="id" />
13 <h:outputLabel for="name" value="Name:" />
14 <h:inputText id="name" value="#{newMember.name}" />
15 <h:message for="name" errorClass="invalid" />
16
17 <h:outputLabel for="email" value="Email:" />
18 <h:inputText id="email" value="#{newMember.email}" />
19 <h:message for="email" errorClass="invalid" />
20
21 <h:outputLabel for="phoneNumber" value="Phone #:" />
22 <h:inputText id="phoneNumber" value="#{newMember.phoneNumber}" />
23 <h:message for="phoneNumber" errorClass="invalid" />
24
25 <h:outputLabel for="address" value="Address:" />
26 <h:inputText id="address" value="#{newMember.address}" />
27 <h:message for="address" errorClass="invalid" />
28 </h:panelGrid>
29
30
31 <h:panelGrid columns="2">
32 <h:commandButton id="register" action="#{memberController.register}"
33 value="Register" styleClass="register" />
34 <h:messages styleClass="messages" errorClass="invalid"
35 infoClass="valid" warnClass="warning" globalOnly="true" />
36 </h:panelGrid>
37
38 </h:form>
39 <h2>Members</h2>
40 <h:panelGroup rendered="#{empty members}">
41 <em>No registered members.</em>
42 </h:panelGroup>
43 <h:dataTable var="_member" value="#{members}"
44 rendered="#{not empty members}" styleClass="simpletablestyle">
45 <h:column>
46 <f:facet name="header">Id</f:facet>
47 #{_member.id}
48 </h:column>
49 <h:column>
50 <f:facet name="header">Name</f:facet>
51 #{_member.name}
52 </h:column>
53 <h:column>
54 <f:facet name="header">Email</f:facet>
55 #{_member.email}
56 </h:column>
57 <h:column>
58 <f:facet name="header">Phone #</f:facet>
59 #{_member.phoneNumber}
60 </h:column>
61 <h:column>
62 <f:facet name="header">Address</f:facet>
63 #{_member.address}
64 </h:column>
65 <h:column>
66 <f:facet name="header">Operation</f:facet>
67 <h:form style="border:none">
68 <h:commandLink action="#{memberController.deleteMemberById}"
69 value="delete">
70 <f:param name="id" value="#{_member.id}"></f:param>
71 </h:commandLink>|
72 <h:commandLink action="#{memberController.findMemberById}"
73 value="update">
74 <f:param name="id" value="#{_member.id}"></f:param>
75 </h:commandLink>
76 </h:form>
77 </h:column>
78 </h:dataTable>
79 </ui:define>
80 </ui:composition>
7、persistence.xml 配置文件
1 <?xml version="1.0" encoding="UTF-8"?>
2
3 <persistence version="2.0"
4 xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5 xsi:schemaLocation="
6 http://java.sun.com/xml/ns/persistence
7 http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
8 <persistence-unit name="primary">
9 <jta-data-source>java:/XE</jta-data-source>
10 <mapping-file>META-INF/orm.xml</mapping-file>
11 <properties>
12 <property name="hibernate.hbm2ddl.auto" value="create-drop" />
13 <property name="hibernate.show_sql" value="true" />
14 <property name="hibernate.format_sql" value="true" />
15 <property name="hibernate.use_sql_comments" value="true"/>
16 </properties>
17 </persistence-unit>
18 </persistence>
注:该文件位于src/main/resources/META-INF/目录下。java:/XE 是Jboss上配置好的一个数据源JNDI字符串。hibernate.hbm2ddl.auto属性值为create-drop,表明webapp启动时,会自动在db中创建表、序列对象,webapp停止时这些对象会自动drop
8、db初始化脚本 import.sql (测试的时候十分有用)
1 insert into MemberHibernate4Demo (id, name, email, phone_number, address) values (SEQ_MEMBER.NEXTVAL, 'John Smith', 'john.smith@mailinator.com', '2125551212', 'Boston NY')
2 insert into MemberHibernate4Demo (id, name, email, phone_number, address) values (SEQ_MEMBER.NEXTVAL, 'Madhumita Sadhukhan', 'msadhukh@gmail.com', '2135551214', 'Brno CZ')
注:该文件位于src/main/resources目录下,webapp启用时将自动执行该文件中的db 脚本
9、其它运行准备: 9.1 要有Oracle Database环境,比如本机可以安装一个Express版本
9.2 Jboss中要配置一个java:/XE的数据源,步骤:
a) 先部署ojdbc6.jar (这是oracle驱动,安装oracle XE或client后,本机安装目录下就能找到)
b) 添加oracle 数据源,数据库驱动选择ojdbc6.jar,连接串参考 jdbc:oracle:thin:@localhost:1521:XE
示例程序下载:http://files.cnblogs.com/yjmyzz/jboss-jpa-sample.zip
运行截图: