EJB 2.x – Entity Beans (BMP – načítanie a uloženie entitného objektu)
Okrem vykonávania rôznych biznis metód, má entitná trieda najviac práce so synchronizovaním svojho stavu s korešpondujúcimi dátami v podkladovej databáze. K tomuto účelu sú určené dve špeciálne metódy, ejbLoad a ejbStore.
Implementácia metódy ejbLoad
EJB kontajner obvykle zavolá túto metódu pri aktivácii entity, kedy je bezpodmienečne nutné zabezpečiť jej synchronizáciu s tým, čo je v databáze. Nasledujúci výpis zobrazuje obsah metódy ejbLoad
entitnej triedy EnglishAuctionBean
.
/* EnglishAuctionBean.java */
public void ejbLoad() {
Connection con = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
con = DSConnectionHelper.getConnection(„auctionSource“);
// vytvoríme príkaz SELECT pre jednotlivé polia aukcie
stmt = con.prepareStatement(„SELECT Name, Description,
Status, StartingBid, MinBidIncrement, ReserveAmount,
StartDate, ScheduledEndDate, ActualEndDate, LeadingBidId,
WinningBidId, ItemId, Quantity FROM auction WHERE id=?“);
Integer primaryKey = (Integer)ctx.getPrimaryKey();
stmt.setInt(1,primaryKey.intValue());
// vykonáme príkaz SELECT
rs = stmt.executeQuery();
if (rs.next()) {
// vložíme hodnoty výsledkov do jednotlivých premenných inštancie
id = primaryKey;
name = rs.getString(„Name“);
description = rs.getString(„Description“);
status = rs.getString(„Status“);
// typ SQL numeric je vrátený ako BigDecimal
BigDecimal bd = rs.getBigDecimal(„StartingBid“);
startingBid = bd != null ? new Double(bd.doubleValue()) : null;
bd = rs.getBigDecimal(„MinBidIncrement“);
minBidIncrement = bd != null ? new Double(bd.doubleValue()) : null;
bd = rs.getBigDecimal(„ReserveAmount“);
reserveAmount = bd != null ? new Double(bd.doubleValue()) : null;
startDateTime = rs.getTimestamp(„StartDate“);
scheduledEndDateTime = rs.getTimestamp(„ScheduledEndDate“);
actualEndDateTime = rs.getTimestamp(„ActualEndDate“);
leadingBidId = (Integer)rs.getObject(„LeadingBidId“);
winningBidId = (Integer)rs.getObject(„WinningBidId“);
itemId = (Integer)rs.getObject(„ItemId“);
quantity = (Integer)rs.getObject(„Quantity“);
item = null;
setBids(null);
leadingBid = null;
winningBid = null;
}
else {
throw new EJBException(„Chyba pri načítaní dát.“);
}
}
catch (SQLException e) {
throw new EJBException;
}
finally {
DSConnectionHelper.cleanup(stmt, con);
}
}
Vo vnútri metódy ejbLoad
môžete využiť inštanciu triedy EntityContext
za účelom získania jej primárneho kľúča. Následne môžete vytvoriť príkaz SELECT, ktorý vytiahne požadované hodnoty atribútov z databázy. Entitná trieda ešte obvykle potrebuje získať referencie na asociované objekty, alebo aspoň zistiť stav ich kľúčových hodnôt, aby ich mohla neskôr v prípade potreby využiť.
Všimnite si, že metóda ejbLoad
momentálne nedrží zoznam všetkých vykonaných ponúk. Stane sa tak až v prípade, keď ich bude treba. Podobne aj čo sa týka poslednej a víťaznej ponuky, nepoznáme ich hodnoty, iba vlastníme odkaz na primárne kľúče spomínaných objektov. Z toho vyplýva, že je iba na vás, čo konkrétne bude metóda ejbLoad
„vyťahovať“ z podkladovej databázy.
Implementácia metódy ejbStore
Náprotivkom metódy ejbLoad
je metóda ejbStore
. EJB kontajner volá túto metódu obvykle v dvoch možných prípadoch. Buď vtedy, keď transakcia obsahujúca entitný objekt bude potvrdená (commit), alebo vtedy, keď má byť entita pasivovaná. Podobne ako pri metóde ejbLoad
, aj tu si musíte zabezpečiť implementáciu metódy ejbStore
vo vlastnej réžii (keďže ide o BMP mechanizmus). Nasledujúci fragment zobrazuje implementáciu metódy ejbStore
pre entitu EnglishAuctionBean
.
/* EnglishAuctionBean.java */
private Collection bidsToStore = new ArrayList();
// v tejto časti sa naplní kolekcia bidsToStore
…
public void ejbStore() {
Connection con = null;
PreparedStatement stmt = null;
try {
con = DSConnectionHelper.getConnection(„auctionSource“);
if (!bidsToStore.isEmpty()) {
// uložíme ponuky pridané počas tejto transkacie
stmt = con.prepareStatement(
„INSERT INTO bid (id, AuctionId, BidderId, BidDateTime,
Amount, TransactionId) VALUES (?,?,?,?,?,?)“);
Iterator iter = bidsToStore.iterator();
while (iter.hasNext()) {
Bid newBid = (Bid)iter.next();
stmt.setInt(1, newBid.getId().intValue());
stmt.setInt(2, newBid.getAuctionId().intValue());
stmt.setInt(3, newBid.getBidderId().intValue());
stmt.setTimestamp(4, newBid.getDateTimeSubmitted());
stmt.setDouble(5, newBid.getAmount().doubleValue());
stmt.setString(6, newBid.getTransactionId());
int rowsInserted = stmt.executeUpdate();
if (rowsInserted != 1) {
throw new EJBException(
„Nemôžem vložiť ponuku do DB.“);
}
}
bidsToStore.clear();
stmt.close();
}
// vytvoríme UPDATE a uložíme stav aukcie do DB
stmt = con.prepareStatement(
„UPDATE auction SET Name = ?, Description = ?,
Status = ?, StartingBid = ?, MinBidIncrement = ?,
ReserveAmount = ?, StartDate = ?, ScheduledEndDate = ?,
ActualEndDate = ?, LeadingBidId = ?, WinningBidId = ?,
ItemId = ?, Quantity = ? FROM auction WHERE id = ?“);
stmt.setString(1, getName());
stmt.setString(2, getDescription());
stmt.setString(3, getStatus());
if (getStartingBid() != null) {
stmt.setDouble(4, getStartingBid().doubleValue());
}
else {
stmt.setNull(4, java.sql.Types.DOUBLE);
}
if (getMinBidIncrement() != null) {
stmt.setDouble(5, getMinBidIncrement().doubleValue());
}
else {
stmt.setNull(5, java.sql.Types.DOUBLE);
}
if (getReserveAmount() != null) {
stmt.setDouble(6, getReserveAmount().doubleValue());
}
else {
stmt.setNull(6, java.sql.Types.DOUBLE);
}
stmt.setTimestamp(7, getStartDateTime());
stmt.setTimestamp(8, getScheduledEndDateTime());
stmt.setTimestamp(9, getActualEndDateTime());
if (getLeadingBid() != null) {
stmt.setInt(10, getLeadingBid().getId().intValue());
}
else {
stmt.setNull(10, java.sql.Types.INTEGER);
}
if (getWinningBid() != null) {
stmt.setInt(11, getWinningBid().getId().intValue());
}
else {
stmt.setNull(11, java.sql.Types.INTEGER);
}
if (getItemId() != null) {
stmt.setInt(12, getItemId().intValue());
}
else {
stmt.setNull(12, java.sql.Types.INTEGER);
}
if (getQuantity() != null) {
stmt.setInt(13, getQuantity().intValue());
}
else {
stmt.setNull(13, java.sql.Types.INTEGER);
}
// nastavíme PK pre WHERE klauzulu
stmt.setInt(14, getId().intValue());
// vykonáme update a ak zlyhá, vyhodíme výnimku
int rowsUpdated = stmt.executeUpdate();
if (rowsUpdated != 1) {
throw new EJBException(„Chyba pri ukladaní dát.“);
}
}
catch (SQLException e) {
// vyhodíme výnimku ak nastane chyba prístupu k DB
throw new EJBException;
}
finally {
// uzatvoríme spojenie
DSConnectionHelper.cleanup(stmt, con);
}
}
Okrem úlohy vykonávať update stavu aukcie, zabezpečuje metóda ejbStore
aj vkladanie nových ponúk (objektov triedy Bid
) do databázy. Nasledujúci výpis zobrazuje implementáciu triedy Bid
.
/**
* File: Bid.java
* Title: Bid
* Description: An auction bid
*/
import java.sql.Timestamp;
public class Bid {
private Integer id;
private Integer auctionId;
private Integer bidderId;
private Timestamp dateTimeSubmitted;
private Double amount;
private String transactionId;
public Bid() {}
public Bid(Integer newId, Integer newAuctionId,
Integer newBidderId, Timestamp newDateTimeSubmitted,
Double newAmount, String newTransactionId) {
setId(newId);
setAuctionId(newAuctionId);
setBidderId(newBidderId);
setDateTimeSubmitted(newDateTimeSubmitted);
setAmount(newAmount);
setTransactionId(newTransactionId);
}
public Integer getId() {
return id;
}
protected void setId(Integer newId) {
if (newId != null) {
id = newId;
}
else {
throw new IllegalArgumentException(„Bid nesmie byť null“);
}
}
public Integer getAuctionId() {
return auctionId;
}
public void setAuctionId(Integer newAuctionId) {
if (newAuctionId != null) {
auctionId = newAuctionId;
}
else {
throw new IllegalArgumentException(„Bid nesmie byť null“);
}
}
public Integer getBidderId() {
return bidderId;
}
public void setBidderId(Integer newBidderId) {
if (newBidderId != null) {
bidderId = newBidderId;
}
else {
throw new IllegalArgumentException(„Bid nesmie byť null“);
}
}
public Timestamp getDateTimeSubmitted() {
return dateTimeSubmitted;
}
public void setDateTimeSubmitted(Timestamp newDateTimeSubmitted) {
if (newDateTimeSubmitted != null) {
dateTimeSubmitted = newDateTimeSubmitted;
}
else {
throw new IllegalArgumentException(„Bid nesmie byť null“);
}
}
public Double getAmount() {
return amount;
}
public void setAmount(Double newAmount) {
if((newAmount != null)&&(newAmount.doubleValue() >= 0.0)) {
amount = newAmount;
}
else {
throw new IllegalArgumentException(
„Bid nesmie byť null alebo záporné číslo“);
}
}
public String getTransactionId() {
return transactionId;
}
public void setTransactionId(String newTransactionId) {
if (newTransactionId != null) {
transactionId = newTransactionId;
}
else {
throw new IllegalArgumentException(„Bid nesmie byť null“);
}
}
public BidView getView() {
BidView view = new BidView(getAuctionId(), getBidderId(),
getDateTimeSubmitted(), getAmount(), getTransactionId());
return view;
}
}
Ako môžete vidieť, najkomplikovanejšou časťou ejbStore
pre aukčnú entitu je kontrola null hodnôt jej jednotlivých atribútov a potom ešte volanie vhodných metód objektu PreparedStatement
.
Problémom tejto jednoduchej implementácie metódy ejbStore
je to, že nie je veľmi efektívna. Pretože zapisuje do databázy vždy, keď je zavolaná, a vždy zapisuje všetky atribúty, bez ohľadu na to, či sa zmenili alebo nie. V niektorom z budúcich článkov si ukážeme, ako tento výkonnostný problém riešiť.
Mohlo by vás také zajímat
-
Proč je důležité tvořit obsah na váš web?
29. srpna 2024 -
AI na dosah ruky: Jak je to s AI v osobních zařízeních?
22. ledna 2024 -
10 nejpopulárnějších programovacích jazyků a jejich využití
9. listopadu 2023
Nejnovější
-
Windows App: Pracujte odkudkoliv, kdykoliv
3. listopadu 2024 -
Od iPhonu po Android: Ultra HDR přináší nový standard fotografií
1. listopadu 2024 -
AI a internetové podvody
29. října 2024 -
Užitečné nástroje pro bezpečnost na internetu
17. října 2024