EJB 3与Java持久化API的应用场景解析
在企业开发中,EJB 3和Java持久化API(JPA)为数据的发布和检索提供了强大的支持。本文将通过几个具体的场景,详细介绍如何利用这些技术来实现不同的数据操作需求。
1. 拦截器与生命周期
首先,我们来看一个拦截器的示例代码:
import javax.interceptor.InvocationContext;
public class StatisticsTooHigh
{
@AroundInvoke
public Object checkIfTooLow(InvocationContext ctx) throws Exception
{
Method method = ctx.getMethod();
if (method.getName().equals("check"))
{
double param = (Double)(ctx.getParameters()[0]);
if (param > 500.0)
{
throw new ImproperArgumentException("Illegal argument: > 500.0");
}
}
// Proceed to the next interceptor
return ctx.proceed();
}
}
拦截器和实现它们的Bean实例具有相同的生命周期属性。在任何
PostConstruct
和
PostActivate
回调被调用之前,拦截器和Bean实例都会被激活。而
PreDestroy
或
PrePassivate
回调会在Bean或拦截器实例执行之前被调用。
2. 场景一:简单表单发布与查询
这个场景通过一个Web表单来发布用户指定的内容,该表单提供了三种不同的联赛属性模板用于数据输入。用户输入球员信息后,数据将显示在输入框下方。
2.1 接口定义
package com.scenario1.ejb.session;
import java.util.*;
import javax.ejb.Local;
import java.util.Collection;
import com.scenario1.persistence.*;
@Local
public interface SessionStatelessLocal
{
public void persist(Object obj);
public Personnel find(String acctNum);
public List findAll();
}
2.2 无状态Bean实现
package com.scenario1.ejb.session;
import com.scenario1.persistence.*;
import javax.ejb.Stateless;
import javax.persistence.PersistenceContext;
import javax.persistence.EntityManager;
import javax.persistence.*;
import java.util.*;
@Stateless
public class SessionStateless implements SessionStatelessLocal {
public SessionStateless() {
}
@PersistenceContext(unitName="sampleEJB3Book")
private EntityManager em;
public Personnel find (String acctNum) {
return em.find(Personnel.class, acctNum);
}
public void persist(Object obj) {
em.persist(obj);
}
public List findAll()
{
List list = em.createQuery("select p from Personnel p").setMaxResults(10).getResultList();
return list;
}
}
2.3 实体类定义
-
Personnel类:
package com.scenario1.persistence;
import javax.persistence.*;
import com.scenario1.common.*;
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="DISCRIMINATORCOLUMN")
public abstract class Personnel extends BasePersonnel
{
public enum Status { HEALTHY, INJURED}
@Id
private String acctNum;
private String name;
private String created;
private Status status;
private float salary;
private String description;
public Personnel(){}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCreated() {
return created;
}
public void setCreated(String created) {
this.created = created;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
public float getSalary() {
return salary;
}
public void setSalary(float salary) {
this.salary = salary;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getAcctNum() {
return acctNum;
}
public void setAcctNum(String acctNum) {
this.acctNum = acctNum;
}
}
-
TeamAccount类:
package com.scenario1.persistence;
import javax.persistence.*;
@MappedSuperclass
public abstract class TeamAccount extends Personnel {
private String teamName;
public TeamAccount() {}
public String getTeamName() {
return teamName;
}
public void setTeamName(String teamName) {
this.teamName = teamName;
}
}
-
TeamA类:
package com.scenario1.persistence;
import javax.persistence.*;
@Entity
public class TeamA extends TeamAccount
{
private float highestBid;
public TeamA() {}
public float getHighestBid() {
return highestBid;
}
public void setHighestBid(float highestBid) {
this.highestBid = highestBid;
}
}
-
TeamAA类:
package com.scenario1.persistence;
import javax.persistence.*;
@Entity
@AttributeOverride(name="teamName", column=@Column(name="team_name"))
public class TeamAA extends TeamAccount
{
private boolean moveUp;
public TeamAA() {}
public boolean getMoveUp() {
return moveUp;
}
public void setMoveUp(boolean moveUp) {
this.moveUp = moveUp;
}
}
2.4 Servlet实现
package com.scenario1.servlet;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.naming.*;
import java.util.*;
import java.io.*;
import com.scenario1.ejb.session.*;
import com.scenario1.persistence.*;
import javax.ejb.*;
public class BaseballServlet extends HttpServlet {
private static final String CREATE_ORDER="createOrder";
@EJB
private SessionStatelessLocal sessionStatelessLocal;
private InitialContext ctx;
public BaseballServlet() {
try {
ctx = new InitialContext();
} catch(Exception ex) {
ex.printStackTrace();
}
}
protected void doGet( HttpServletRequest request, HttpServletResponse response
) throws ServletException, IOException {
processAction(request, response);
}
protected void doPost( HttpServletRequest request, HttpServletResponse response
) throws ServletException, IOException {
processAction(request, response);
}
private void processAction(HttpServletRequest request, HttpServletResponse
response) throws IOException {
String action = request.getParameter("action");
response.setContentType("text/html");
ServletOutputStream out = response.getOutputStream();
if(action == null || "".equals(action)) {
response.sendRedirect("index.html");
} else if("createAccount".equalsIgnoreCase(action)) {
String accountType = request.getParameter("accountType");
out.println("<html><head><title>Java Persistence Example</title></head>");
out.println("<body><form name=\"submitForm\" action=\"/sampleEJB3Book/BaseballServlet\" method=\"post\">");
out.println("<table border=\"1\" align=\"center\" width=\"75%\" valign=\"center\">");
out.println("<tr><td colspan=\"2\" align=\"center\" bgcolor=\"#cccccc\"><h2><b>Enter New Player (" + accountType + ")</b></h2></td></tr>");
out.println("<tr><td>Account Number</td><td><input type=\"text\" name=\"acctNum\"></td></tr>");
out.println("<tr><td>Name</td><td><input type=\"text\" name=\"acctName\"></td></tr>");
out.println("<tr><td>Status</td><td><select name=\"status\"><option value=\"healthy\" selected=\"true\">Healthy</option><option value=\"injured\">Injured</option></select></td></tr>");
out.println("<tr><td>Description</td><td><input type=\"text\" name=\"description\"></td></tr>");
out.println("<tr><td>Salary</td><td><input type=\"text\" name=\"salary\"></td></tr>");
out.println("<tr><td>Team</td><td><input type=\"text\" name=\"team\"></td></tr>");
if("TeamA".equalsIgnoreCase(accountType)) {
out.println("<tr><td>Move up?</td><td><select name=\"moveup\"><option value=\"yes\" selected=\"true\">Yes</option><option value=\"no\">No</option></select></td></tr>");
out.println("<tr><td colspan=\"2\" align=\"center\"> <input type=\"hidden\" name=\"accountType\" value=\"TeamA\"></td></tr>");
} else if("TeamAA".equalsIgnoreCase(accountType)) {
out.println("<tr><td>Savings Rate</td><td><input type=\"text\" name=\"savingsRate\"></td></tr>");
out.println("<tr><td colspan=\"2\" align=\"center\"> <input type=\"hidden\" name=\"accountType\" value=\"TeamAA\"></td></tr>");
}
out.println("<tr><td colspan=\"2\" align=\"center\"> <input type=\"submit\" name=\"submit\" value=\"Submit\"></td></tr>");
out.println("<tr><td colspan=\"2\" align=\"center\"> <input type=\"hidden\" name=\"action\" value=\"persistAccount\"></td></tr>");
out.println("<tr><td colspan=\"2\" align=\"center\"> <input type=\"hidden\" name=\"accountType\" value=\"" + accountType+ "\"></td></tr>");
out.println("</table>");
} else if ("persistAccount".equalsIgnoreCase(action))
{
String accountType = request.getParameter("accountType");
String acctNum = request.getParameter("acctNum");
String name = request.getParameter("acctName");
String salary = request.getParameter("salary");
String description = request.getParameter("description");
String status = request.getParameter("status");
String team = request.getParameter("team");
Personnel account = null;
if("TeamA".equalsIgnoreCase(accountType)) {
float fBid=0;
try {
String bid = request.getParameter("highestBid");
if ( (bid == null) || (bid.equals("")) )
fBid = 0;
else
fBid=Float.valueOf(bid);
} catch(Exception ex) {
ex.printStackTrace();
}
account = new TeamA();
((TeamA)account).setHighestBid(fBid);
((TeamA)account).setTeamName(team);
}
else if("TeamAA".equalsIgnoreCase(accountType))
{
String moveUp = request.getParameter("moveUp");
account = new TeamAA();
((TeamAA)account).setMoveUp("yes".equalsIgnoreCase(moveUp));
((TeamAA)account).setTeamName(team);
}
else if("TeamAAA".equalsIgnoreCase(accountType))
{
String moveUp = request.getParameter("moveUp");
account = new TeamAA();
((TeamAAA)account).setMoveUp("yes".equalsIgnoreCase(moveUp));
}
float fSalary=0;
try {
fSalary=Float.valueOf(request.getParameter("salary"));
} catch(Exception ex) {
ex.printStackTrace();
}
String szStatus = request.getParameter("status");
account.setAcctNum(acctNum);
account.setSalary(fSalary);
account.setDescription(request.getParameter("description"));
account.setName(name);
if("injured".equalsIgnoreCase(szStatus))
account.setStatus(Personnel.Status.INJURED);
else
account.setStatus(Personnel.Status.HEALTHY);
sessionStatelessLocal.persist(account);
out.println("<html><head><title>Test</title></head><body><form name=\"submitForm\" action=\"/sampleEJB3Book/BaseballServlet\" method=\"post\"><table cellspacing=\"3\" cellpadding=\"3\" align=\"center\" width=\"50%\" valign=\"center\"><th>Test</th><tr><td> </td></tr>");
out.println("<tr><td colspan=\"2\" align=\"center\">Account information was successfully saved.</td></tr>");
out.println("<tr><td colspan=\"2\" align=\"center\"> <input type=\"submit\" name=\"submit\" value=\"Submit\"></td></tr>");
out.println("</form></body></html>");
}
out.println("<br><br>");
out.println("<table border=\"1\" width=\"100%\">");
out.println("<tr><td bgcolor=\"#cccccc\">#</td><td bgcolor=\"#cccccc\">Account #</td><td bgcolor=\"#cccccc\">Name</td><td bgcolor=\"#cccccc\">Description</td><td bgcolor=\"#cccccc\">Salary</td></tr>");
List list = sessionStatelessLocal.findAll();
if ( (list == null) || (list.size() == 0) )
out.println("<tr><td colspan=\"5\" align=\"center\"> No players available</td></tr>");
else
{
for (int i=0; i < list.size(); i++)
{
Personnel p = (Personnel)list.get(i);
out.println("<tr>");
out.println("<td>" + (i+1) + "</td>");
out.println("<td>" + p.getAcctNum() + "</td>");
out.println("<td>" + p.getName() + "</td>");
out.println("<td>" + p.getDescription() + "</td>");
out.println("<td>" + p.getSalary() + "</td>");
out.println("</tr>");
}
}
out.println("</table>");
}
}
2.5 持久化配置
为了启用Derby数据库的
java2db
功能,
persistence.xml
文件需要包含以下内容:
<persistence...>
<persistence-unit name =...>
<!-- the datasource affiliated with the bundled derby database -->
<jta-data-source>jdbc/__default</jta-data-source>
<properties>
<!--Enable the java2db feature -->
<property name="toplink.ddl-generation" value="drop-and-create-tables"/>
</properties>
</persistence-unit>
</persistence>
persistence.xml
文件中可定义的属性如下表所示:
| 属性 | 描述 |
| — | — |
|
toplink.ddl-generation
| 默认值为
none
,可能的值有
create-tables
、
drop-and-create-tables
和
none
|
|
toplink.create-ddl-jdbc-file-name
| 创建表的JDBC DDL文件名 |
|
toplink.drop-ddl-jdbc-file-name
| 删除表的JDBC DDL文件名 |
|
toplink.application-location
| 应用程序生成的目录,定义JDBC DDL文件的存储位置 |
3. 场景二:一对多关系的数据库操作
这个场景展示了如何使用应用服务器的容器管理持久化(CMP)机制构建一个具有一对多数据库关系的简单Web组件。
3.1 接口定义
package com.scenario2.ejb.session;
import javax.ejb.Local;
import com.scenario2.persistence.*;
import com.scenario2.common.*;
import java.util.List;
@Local
public interface PlayersSessionLocal
{
public Players searchForPlayers(String id);
public void persist(Object obj);
public List findPlayersByName(String name);
public List findPlayersByTeam(String team);
public void remove(Object obj);
}
3.2 无状态Bean实现
package com.scenario2.ejb.session;
import javax.ejb.Stateless;
import javax.ejb.Stateful;
import javax.ejb.SessionContext;
import javax.persistence.*;
import javax.ejb.*;
import java.util.List;
import com.scenario2.persistence.*;
import com.scenario2.common.*;
@Stateless
@TransactionManagement(value=TransactionManagementType.CONTAINER)
public class PlayersSession implements PlayersSessionLocal, PlayersSessionRemote
{
@javax.persistence.PersistenceContext(unitName="persistence_sample")
private EntityManager em;
public PlayersSession(){}
public Players searchForPlayers(String id) {
Players players = (Players)em.find(Players.class, id);
return players;
}
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void remove(Object obj) {
Object mergedObj = em.merge(obj);
em.remove(mergedObj);
}
public void persist(Object obj) {
em.persist(obj);
}
public List findPlayersByName(String name)
{
List players =
em.createNamedQuery("findPlayersByName").setParameter("name",
name).getResultList();
return players;
}
public List findPlayersByTeam(String team)
{
List players =
em.createNamedQuery("findPlayersByTeam").setParameter("team",
team).getResultList();
return players;
}
}
3.3 实体类定义
package com.scenario2.persistence;
import java.util.Vector;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import javax.persistence.*;
import javax.persistence.OneToMany;
@Entity
@NamedQueries(
value=
{
@NamedQuery(name="findPlayersByName", query="select object(p) from Players p where p.name= :name"),
@NamedQuery(name="findPlayersByTeam", query="select object(p) from Players p where p.team= :team")
}
)
public class Players implements java.io.Serializable
{
private int playerId;
private String name;
private String team;
private String position;
private int teamId;
public Players(int playerId, String name, String team, String position, int
teamId) {
setPlayerId(playerId);
setName(name);
setTeam(team);
setPosition(position);
setTeamId(teamId);
}
public Players() {}
@Id
@Column(name="playerId")
public int getPlayerId() {
return playerId;
}
public void setPlayerId(int playerId){
this.playerId = playerId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTeam() {
return team;
}
public void setTeam(String team) {
this.team = team;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
public int getTeamId() {
return teamId;
}
public void setTeamId(int teamId) {
this.teamId = teamId;
}
@PostPersist
public void postCreate () {
System.out.println("Players::postCreate:");
}
@PostRemove
public void ejbRemove() {
System.out.println("Players::postRemove");
}
}
3.4 部署描述符
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<session-config>
<session-timeout>
600
</session-timeout>
</session-config>
<ejb-local-ref>
<description> EJB Session</description>
<ejb-ref-name>PlayersSessionLocal</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local-home></local-home>
<local> com.scenario2.ejb.session.PlayersSessionLocal</local>
<ejb-link>PlayersSession</ejb-link>
</ejb-local-ref>
<welcome-file-list>
<welcome-file>
index.jsp
</welcome-file>
</welcome-file-list>
</web-app>
3.5 前端页面与业务逻辑
-
createPlayers.jsp:
<%@ page language="java" %>
<%@ page import="javax.naming.InitialContext" %>
<%@ page import=" com.scenario2.persistence.Players" %>
<%@ page import=" com.scenario2.ejb.session.*" %>
<%@ page import='java.util.*' %>
<html>
<head><title>Create Players</title></head>
<body bgcolor="white">
<center>
<h2>Create Players</h2>
<form method="post" action="/baseball/createPlayers.jsp">
<table border="0">
<tr>
<td>Player ID : </td>
<td><input type="text" name="playerId" size="11" value=""></td>
</tr>
<tr>
<td>Name : </td>
<td><input type="text" name="name" size="25" value=""></td>
</tr>
<tr>
<td>Team : </td>
<td><input type="text" name="team" size="25" value=""></td>
</tr>
<tr>
<td>Position : </td>
<td><input type="text" name="position" size="25" value=""></td>
</tr>
<tr>
<td>Team ID : </td>
<td><input type="text" name="teamId" size="25" value=""></td>
</tr>
</table>
<input type="submit" name="submit" value="Submit">
</form>
<%
String playerId = request.getParameter("playerId");
String name = request.getParameter("name");
String team = request.getParameter("team");
String position = request.getParameter("position");
String teamId = request.getParameter("teamId");
if (playerId != null && !"".equals(playerId))
{
try {
InitialContext ic = new InitialContext();
Object o = ic.lookup("java:comp/env/PlayersSessionLocal");
PlayersSessionLocal playersSession = (PlayersSessionLocal) o;
Players player = new Players(Integer.parseInt(playerId), name, team,
position, Integer.parseInt(teamId));
playersSession.persist(player);
%>
New player created :
<b>
<%=player.getPlayerId()%>,
<%=player.getName()%>,
<%=player.getTeam()%>,
<%=player.getPosition()%>,
<%=player.getTeamId()%>
</b>
<%
} catch(Exception e) {
e.printStackTrace();
out.println("EXCEPTION : " + e.toString());
}
}
%>
<hr>
[<a href="/baseball/index.html">HOME</a>]
</center>
</body>
</html>
-
searchTeam.jsp:
<%@ page language="java" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.Collection" %>
<%@ page import="javax.ejb.ObjectNotFoundException" %>
<%@ page import="javax.naming.InitialContext" %>
<%@ page import=" com.scenario2.persistence.Players" %>
<%@ page import=" com.scenario2.ejb.session.*" %>
<%@ page import='java.util.*' %>
<html>
<head><title>Test</title></head>
<body bgcolor="white">
<center>
<html>
<head><title>Search Team</title></head>
<body bgcolor="white">
<center>
<h2>Search Team</h2>
<form method="post" action="/baseball/searchTeam.jsp">
<table border="0">
<tr>
<td>Select criteria : </td>
<td align="center">
<input type="radio" name="criteria" value="player">player
<input type="radio" name="criteria" value="team">team
</td>
</tr>
<tr>
<td>Search for : </td>
<td><input type="text" name="searchString" size="25" value=""></td>
</tr>
</table>
<input type="submit" name="submit" value="Submit">
</form>
<%
String criteria = request.getParameter("criteria");
String searchString = request.getParameter("searchString");
if (searchString != null && !"".equals(searchString))
{
try {
InitialContext ic = new InitialContext();
Object o = ic.lookup("java:comp/env/PlayersSessionLocal");
PlayersSessionLocal playersSession = (PlayersSessionLocal) o;
List players = new ArrayList();
String label = "Search criteria: ";
if (criteria.equals("player"))
{
label += ("(player=" + searchString + ")<br>");
players = playersSession.findPlayersByName(searchString);
}
else if (criteria.equals("team"))
{
label += ("(team=" + searchString + ")<br>");
players = playersSession.findPlayersByTeam(searchString);
}
out.println(label);
if (players.size() > 0)
{
for (int i = 0; i < players.size(); i++)
{
Players p = (Players)(players).get(i);
String pName = (String)p.getName();
String pPosition = (String)p.getPosition();
out.println(pName + " plays position: " + pPosition + "<br>");
}
}
}
catch(Exception e)
{
e.printStackTrace();
out.println(e.toString());
}
}
%>
<hr>
[<a href="/baseball/index.html">HOME</a>]
</center>
</body>
</html>
</center>
</body>
</html>
4. 场景三:多对多关系的数据库操作
此场景展示了如何管理具有多对多关系的表,用于处理球队所有者的选秀选择。
4.1 接口定义
package com.scenario3.ejb.session;
import javax.ejb.Local;
import com.scenario3.persistence.*;
import java.util.List;
@Local
public interface OwnersSessionLocal
{
public Owners searchForOwners(String id);
public DraftPicks searchForDraftPicks(String id);
public void persist(Object obj);
public List findAllDraftPicks();
public void remove(Object obj);
public Owners removeOwnersDraftPicks(String ownr, String pick);
public Owners addOwnersDraftPicks(String ownr, String pick);
}
4.2 无状态Bean实现
package com.scenario3.ejb.session;
import javax.ejb.Stateless;
import javax.ejb.Stateful;
import javax.ejb.SessionContext;
import javax.persistence.*;
import javax.ejb.*;
import java.util.List;
import java.util.Collection;
import com.scenario3.persistence.*;
@Stateless
@TransactionManagement(value=TransactionManagementType.CONTAINER)
public class OwnersSession implements OwnersSessionLocal, OwnersSessionRemote {
@javax.persistence.PersistenceContext(unitName="persistence_sample")
private EntityManager em;
public OwnersSession() {}
public Owners searchForOwners(String id) {
Owners owners = (Owners)em.find(Owners.class, id);
return owners;
}
public DraftPicks searchForDraftPicks(String id) {
DraftPicks draftPicks = (DraftPicks)em.find(DraftPicks.class, id);
return draftPicks;
}
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void remove(Object obj) {
Object mergedObj = em.merge(obj);
em.remove(mergedObj);
}
public void persist(Object obj) {
em.persist(obj);
}
public List findAllDraftPicks() {
List draftPicks = em.createNamedQuery("findAllDraftPicks").getResultList();
return draftPicks;
}
public Owners removeOwnersDraftPicks(String ownr, String pick) {
Owners owners = null;
DraftPicks draftPicks = null;
try {
owners = (Owners)em.find(Owners.class, ownr);
draftPicks = (DraftPicks)em.find(DraftPicks.class, pick);
if(!owners.getDraftpicks().contains(draftPicks)) {
System.out.println("remove: did not find a draft pick obj for :" +
draftPicks.getName());
} else {
owners.getDraftpicks().remove(draftPicks);
draftPicks.getOwners().remove(owners);
}
} catch(Exception e) {
e.printStackTrace();
}
return owners;
}
public Owners addOwnersDraftPicks(String ownr, String pick) {
Owners owners = null;
DraftPicks draftPicks = null;
try {
owners = (Owners)em.find(Owners.class, ownr);
draftPicks = (DraftPicks)em.find(DraftPicks.class, pick);
if(owners.getDraftpicks().contains(draftPicks)) {
System.out.println("add: found an existing subscription obj for :"
+ draftPicks.getName());
} else {
owners.getDraftpicks().add(draftPicks);
draftPicks.getOwners().add(owners);
}
} catch(Exception e) {
e.printStackTrace();
}
return owners;
}
}
4.3 实体类定义
-
DraftPicks类:
package com.scenario3.persistence;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import javax.persistence.*;
@Entity
@NamedQuery(name="findAllDraftPicks", query="select d from DraftPicks d")
public class DraftPicks implements java.io.Serializable {
private String name;
private String position;
private Collection owners;
public DraftPicks() {}
@Id
public String getName() { // primary key
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
@ManyToMany(mappedBy="draftpicks", targetEntity=
com.scenario3.persistence.Owners.class)
public Collection<Owners> getOwners() {
return owners;
}
public void setOwners(Collection owners) {
this.owners = owners;
}
public DraftPicks(String name, String position) {
_create(name, position);
}
private String _create(String name, String position) {
setName(name);
setPosition(position);
return name;
}
}
-
Owners类:
package com.scenario3.persistence;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import javax.persistence.*;
import javax.persistence.OneToMany;
@Entity
public class Owners implements java.io.Serializable
{
private String ownerId;
private String firstName;
private String lastName;
private Collection draftpicks;
public Owners() {}
@Id
@Column(name="OWNERID")
public String getOwnerId() {
return ownerId;
}
public void setOwnerId(String ownerId) {
this.ownerId = ownerId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName=firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName=lastName;
}
public Owners(String ownerId, String firstName, String lastName) {
setOwnerId(ownerId);
setFirstName(firstName);
setLastName(lastName);
}
@ManyToMany(targetEntity= com.scenario3.persistence.DraftPicks.class,
fetch=FetchType.EAGER )
@JoinTable(
name="OWNERSDRAFTPICKS",
joinColumns=@JoinColumn(name="OWNERS_OWNERS",
referencedColumnName="OWNERID"),
inverseJoinColumns=@JoinColumn(name="DRAFTPICKS_NAME",
referencedColumnName="NAME")
)
public Collection<DraftPicks> getDraftpicks() {
return draftpicks;
}
public void setDraftpicks (Collection draftpicks) {
this.draftpicks=draftpicks;
}
@Transient
public ArrayList getDraftpicksList() {
ArrayList list = new ArrayList();
Iterator c = getDraftpicks().iterator();
while (c.hasNext()) {
list.add((DraftPicks)c.next());
}
return list;
}
@PostPersist
public void postCreate () {
System.out.println("[Owners:postCreate]");
}
@PostRemove
public void ejbRemove() {
System.out.println("[Owners:postRemove]");
}
}
4.4 前端页面与业务逻辑
editOwner.jsp
:
<%@ page language="java" %>
<%@ page import="java.util.Collection" %>
<%@ page import="javax.naming.InitialContext" %>
<%@ page import=" com.scenario3.persistence.Owners" %>
<%@ page import=" com.scenario3.persistence.DraftPicks" %>
<%@ page import=" com.scenario3.ejb.session.*" %>
<%@ page import=" com.scenario3.common.*" %>
<%@ page import='java.util.*' %>
<html>
<head><title>Test</title></head>
<body bgcolor="white">
<center>
<h2>Baseball Draft</h2>
<%
System.out.println("getting params");
String oid = request.getParameter("oid");
String draftpicks = request.getParameter("draftpicks");
String[] removeitem = request.getParameterValues("removeitem");
String name = "";
String position = "";
if (draftpicks != null) {
String[] playerposition = draftpicks.split("[|]");
if (playerposition.length == 2) {
name = playerposition[0];
position = playerposition[1];
}
}
Owners owners = null;
OwnersSessionLocal ownersSession = null;
if ( (oid != null) && (!oid.equals("")) ) {
try {
InitialContext ic = new InitialContext();
Object o = ic.lookup("java:comp/env/OwnersSessionLocal");
ownersSession = (OwnersSessionLocal) o;
owners = ownersSession.searchForOwners(oid);
} catch(Exception e) {
e.printStackTrace();
out.println(e.toString());
}
if (owners != null) {
%>
<table border="0">
<tr bgcolor="#cccccc"><td>Owner</td><td>First Name</td><td>Last Name</td></tr>
<tr>
<td><%=owners.getOwnerId()%></td>
<td><%=owners.getFirstName()%></td>
<td><%=owners.getLastName()%></td>
</tr>
<tr><td colspan="3"> </td></tr>
</table>
<%
}
}
if ( (removeitem != null) && (removeitem.length > 0) ) {
for (int i=0; i < removeitem.length; i++) {
try {
System.out.println("removing oid, name= " + oid + ", " +
removeitem[i]);
owners = ownersSession.removeOwnersDraftPicks(oid, removeitem[i]);
} catch(Exception e) {
e.printStackTrace();
}
}
}
String userSubmit = request.getParameter("submit");
if ( (userSubmit != null && userSubmit.equals("Add Draft Pick")) &&
(!name.equals("")) ) {
try {
System.out.println("adding oid, name= " + oid + ", " + name);
owners = ownersSession.addOwnersDraftPicks(oid, name);
} catch(Exception e) {
e.printStackTrace();
out.println(e.toString());
}
}
List allDraftPicks = null;
try {
allDraftPicks = ownersSession.findAllDraftPicks();
} catch(Exception e) {
e.printStackTrace();
out.println(e.toString());
}
%>
<form method="post" action="/baseball/editOwner.jsp">
<table border="1">
<%
if ( (allDraftPicks == null) || (allDraftPicks.size() == 0)) {
%>
<tr>
<td colspan="2">No draft picks found.</td>
</tr>
<%
} else {
%>
<tr>
<td>
<select name="draftpicks">
<%
for (int i = 0; i < allDraftPicks.size(); i++)
{
DraftPicks draftPicks = (DraftPicks)allDraftPicks.get(i);
%>
<option
value="<%=draftPicks.getName()%>|<%=draftPicks.getPosition()%>">
<%=draftPicks.getName()%>
</option>
<%
}
%>
</select>
</td>
</tr>
<%
}
%>
<tr>
<td colspan="2" align="center">
<input type="submit" name="submit" value="Add Draft Pick">
<input type="hidden" name="oid" value="<%=oid%>">
</td>
</tr>
</table>
</form>
<form method="post" action="/baseball/editOwner.jsp">
<table>
<tr bgcolor="#cccccc"><td colspan="3" align="center">ID:<%=oid%>'s List</td></tr>
<tr bgcolor="#cccccc">
<td>Name</td>
<td>Position</td>
<td><input type="submit" name="remove" value="Remove?"></td>
<input type="hidden" name="oid" value="<%=oid%>">
<input type="hidden" name="draftpicks" value="<%=draftpicks%>">
</tr>
<%
if (owners != null) {
List ownersList = owners.getDraftpicksList();
if ( (ownersList != null) && (ownersList.size() > 0) ) {
for (int i=0; i < ownersList.size(); i++) {
DraftPicks draftPicks = (DraftPicks)ownersList.get(i);
%>
<tr>
<td><%=draftPicks.getName()%></td>
<td><%=draftPicks.getPosition()%></td>
<td><input type="checkbox" name="removeitem" value="<%=draftPicks.getName()%>"></td>
</tr>
<%
}
}
}
%>
</table>
</form>
</center>
</body>
</html>
通过以上三个场景的介绍,我们可以看到EJB 3和Java持久化API在不同数据库关系和业务需求下的强大应用能力。无论是简单的表单发布与查询,还是复杂的多对多关系处理,都能通过合理的设计和编码来实现。在实际开发中,我们可以根据具体的业务场景选择合适的技术和设计方案,以提高开发效率和系统性能。
EJB 3与Java持久化API的应用场景解析
总结与对比
为了更清晰地理解不同场景下的应用,我们对上述三个场景进行总结和对比,如下表所示:
| 场景 | 数据库关系 | 主要操作 | 关键类和接口 |
| — | — | — | — |
| 场景一 | 无特定复杂关系 | 表单数据的发布与查询 |
SessionStatelessLocal
、
SessionStateless
、
Personnel
等 |
| 场景二 | 一对多关系 | 球员数据的创建、查询和删除 |
PlayersSessionLocal
、
PlayersSession
、
Players
|
| 场景三 | 多对多关系 | 球队所有者选秀选择的管理 |
OwnersSessionLocal
、
OwnersSession
、
Owners
、
DraftPicks
|
从这个表格中可以看出,不同的数据库关系对应着不同的业务操作和关键类。在实际开发中,我们需要根据具体的业务需求来选择合适的场景和对应的技术实现。
技术点分析
拦截器的作用
拦截器在企业开发中起着重要的作用。以
StatisticsTooHigh
类为例,它使用了
@AroundInvoke
注解来拦截方法调用。在
checkIfTooLow
方法中,会检查方法名是否为
check
,如果是,则进一步检查传入的参数是否大于500.0,如果大于则抛出异常。这种拦截机制可以在方法执行前后进行一些额外的处理,如参数验证、日志记录等,从而增强系统的健壮性和可维护性。
资源注入的优势
在上述场景中,我们多次使用了资源注入,如
@PersistenceContext
和
@EJB
注解。资源注入的主要优势在于简化了环境访问,避免了使用JNDI查询的复杂性。通过注解,我们可以直接在类中注入所需的资源,如
EntityManager
和EJB实例,使得代码更加简洁和易于维护。
命名查询的使用
命名查询是JPA中一个非常实用的特性。在场景二和场景三中,我们使用了
@NamedQueries
和
@NamedQuery
注解来定义命名查询。命名查询的好处在于可以将查询语句集中管理,提高了代码的可读性和可维护性。同时,命名查询在编译时会进行语法检查,减少了运行时的错误。
操作步骤总结
场景一操作步骤
-
定义接口
:创建
SessionStatelessLocal接口,定义持久化、查询等方法。 -
实现无状态Bean
:创建
SessionStateless类,实现接口方法,并使用@PersistenceContext注入EntityManager。 -
定义实体类
:创建
Personnel、TeamAccount、TeamA、TeamAA等实体类,使用JPA注解进行映射。 -
实现Servlet
:创建
BaseballServlet类,处理用户请求,根据不同的操作类型进行相应的处理。 -
配置持久化
:在
persistence.xml文件中配置数据源和相关属性,启用java2db功能。
场景二操作步骤
-
定义接口
:创建
PlayersSessionLocal接口,定义搜索、持久化、删除等方法。 -
实现无状态Bean
:创建
PlayersSession类,实现接口方法,使用@PersistenceContext注入EntityManager。 -
定义实体类
:创建
Players类,使用@NamedQueries定义命名查询。 -
配置部署描述符
:在
web.xml文件中配置EJB本地引用。 -
实现前端页面和业务逻辑
:创建
createPlayers.jsp和searchTeam.jsp页面,处理球员数据的创建和查询。
场景三操作步骤
-
定义接口
:创建
OwnersSessionLocal接口,定义搜索、持久化、删除、添加选秀选择等方法。 -
实现无状态Bean
:创建
OwnersSession类,实现接口方法,使用@PersistenceContext注入EntityManager。 -
定义实体类
:创建
Owners和DraftPicks类,使用@ManyToMany注解定义多对多关系。 -
实现前端页面和业务逻辑
:创建
editOwner.jsp页面,处理球队所有者选秀选择的管理。
流程图展示
下面是场景二的操作流程图,使用mermaid语法表示:
graph TD;
A[用户访问createPlayers.jsp] --> B[输入球员信息并提交];
B --> C[调用PlayersSessionLocal的persist方法];
C --> D[将球员信息保存到数据库];
E[用户访问searchTeam.jsp] --> F[选择搜索条件并输入搜索值];
F --> G[调用PlayersSessionLocal的findPlayersByName或findPlayersByTeam方法];
G --> H[从数据库查询球员信息];
H --> I[将查询结果显示在页面上];
这个流程图清晰地展示了场景二中球员数据的创建和查询过程。用户在前端页面输入信息,通过EJB接口调用相应的方法,最终实现数据的持久化和查询。
实际应用建议
在实际开发中,我们可以根据具体的业务需求和数据库关系选择合适的场景和技术实现。同时,为了提高系统的性能和可维护性,我们还可以考虑以下几点建议:
1.
合理使用缓存
:对于一些频繁查询的数据,可以使用缓存机制来减少数据库的访问次数,提高系统的响应速度。
2.
事务管理
:在涉及到数据库操作时,要合理使用事务管理,确保数据的一致性和完整性。可以使用
@TransactionAttribute
注解来控制事务的行为。
3.
代码优化
:对代码进行优化,避免不必要的重复查询和数据处理。可以使用批量操作和预编译查询来提高性能。
4.
错误处理
:在代码中添加适当的错误处理机制,捕获和处理可能出现的异常,提高系统的健壮性。
通过以上的分析和建议,我们可以更好地应用EJB 3和Java持久化API来开发企业级应用。在实际项目中,要根据具体情况灵活运用这些技术,不断优化和改进系统,以满足业务的需求。
总之,EJB 3和Java持久化API为企业开发提供了强大的支持,通过合理的设计和编码,我们可以实现各种复杂的业务需求。希望本文对大家在学习和使用这些技术时有所帮助。
超级会员免费看
35

被折叠的 条评论
为什么被折叠?



