JPA EJB3 – ví dụ mối quan hệ giữa các bảng trong CSDL
Trong ví dụ này, tôi sẽ hướng dẫn các bạn tạo 1 EJB thao tác trên nhiều bảng CSDL và giữa các bảng này có mối quan hệ với nhau.
1. Tạo Database:
Hệ cơ sở dữ liệu ở đây tôi sử dụng dùng MS SQL Server 2005. Database có tên BookMS với các bảng và mối quan hệ của chúng được cho như hình sau:
Đây là script sinh ra database này:
SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[BookType]’) AND type in (N’U’)) BEGIN CREATE TABLE [dbo].[BookType]( [typeID] [int] NOT NULL, [typeName] [nvarchar](250) NOT NULL, CONSTRAINT [PK_BookType] PRIMARY KEY CLUSTERED ( [typeID] ASC )WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY] ) ON [PRIMARY] END GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Publisher]’) AND type in (N’U’)) BEGIN CREATE TABLE [dbo].[Publisher]( [pubID] [int] NOT NULL, [pubName] [nvarchar](150) NOT NULL, CONSTRAINT [PK_Publisher] PRIMARY KEY CLUSTERED ( [pubID] ASC )WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY] ) ON [PRIMARY] END GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Book]’) AND type in (N’U’)) BEGIN CREATE TABLE [dbo].[Book]( [ISBN] [bigint] NOT NULL, [bookTiitle] [nvarchar](250) NOT NULL, [authorName] [nvarchar](250) NOT NULL, [pubID] [int] NOT NULL, [typeID] [int] NOT NULL, [shortDesc] [ntext] NOT NULL, CONSTRAINT [PK_Book] PRIMARY KEY CLUSTERED ( [ISBN] ASC )WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY] ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] END GO IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_Book_BookType]’) AND parent_object_id = OBJECT_ID(N'[dbo].[Book]’)) ALTER TABLE [dbo].[Book] WITH CHECK ADD CONSTRAINT [FK_Book_BookType] FOREIGN KEY([typeID]) REFERENCES [dbo].[BookType] ([typeID]) GO IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_Book_Publisher]’) AND parent_object_id = OBJECT_ID(N'[dbo].[Book]’)) ALTER TABLE [dbo].[Book] WITH CHECK ADD CONSTRAINT [FK_Book_Publisher] FOREIGN KEY([pubID]) REFERENCES [dbo].[Publisher] ([pubID]) GO IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK1FAF0945FA8708]’) AND parent_object_id = OBJECT_ID(N'[dbo].[Book]’)) ALTER TABLE [dbo].[Book] WITH CHECK ADD CONSTRAINT [FK1FAF0945FA8708] FOREIGN KEY([typeID]) REFERENCES [dbo].[BookType] ([typeID]) GO IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK1FAF098EFB6544]’) AND parent_object_id = OBJECT_ID(N'[dbo].[Book]’)) ALTER TABLE [dbo].[Book] WITH CHECK ADD CONSTRAINT [FK1FAF098EFB6544] FOREIGN KEY([pubID]) REFERENCES [dbo].[Publisher] ([pubID]) |
Tôi sử dụng Eclipse ganymede (3.4) để thực hiện ví dụ này.
2. Cấu hình Data Management
Bạn phải cấu hình kết nối đến CSDL trong Eclipse. Điều này bắt buộc bạn phải có JDBC driver của MS SQLServer. Bạn có thể download tại http://www.microsoft.com. Sau khi download xong, bạn giải nén ra 1 thư mục nào đó và ghi nhớ lại thư mục này, đặc biệt là file sqljdbc.jar
Trong eclipse, bạn vào menu Window->Reference, chọn mục “Data Management->Connectivity->Driver Definition” như hình
Nhấn nút Add để thêm, cửa sổ sau xuất hiện
Ở lớp Jar List, nhấn nút Add Jars/Zip… rồi chọn file jar sqljdbc.jar
Ở lớp Properties, gõ database name, gõ username, password. lưu ý phải có password. Bạn nên tạo 1 user name khác trong sqlserver với 1 pass và cấp quyền cho nó chứ không dùng sa!!!
Nhấn OK, bạn đã có 1 Driver Definition.
3. Tạo EJB Project
Trong Eclipse, bạn vào menu File->New->EJB Project. Đặt tên là BookMS_JPA. Nhấn nút Modify trong mục Configuration và nhớ chọn mục “Java Persistence 1.0“.
Nhấn Next 2 lần và chọn lựa các tùy chọn như hình sau
Nhấn Finish để kết thúc việc tạo EJB Project
4. Sinh ra các Entities (Entity-Bean)
Nhấn chuột phải lên project của chúng ta, chọn “JPA Tools->Generate Entities”
Nhấn Next
Nhấn Finish để kết thúc.
Bạn sẽ gặp 1 số lỗi khi xem code được phát sinh. Bạn phải fix nó bằng cách thay đổi perspective thành JPA (vào menu WIndow->Open Perspective ->Others, chọn JPA nhấn OK).
Ở góc dưới bên phải của perspective này bạn chọn tab JPA Details, thay đổi Schema thành schema mà bạn config (ở đây là dbo) như hình,
Sau đó lưu lại, các lỗi đã được fix.
Cấu hình persistence
Mở file Persistence.xml trong mục META-INF, thay đổi nội dung như sau
<?xml version=”1.0″ encoding=”UTF-8″?> <persistence version=”1.0″ 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_1_0.xsd”> <persistence-unit name=”EbookMS_JPA”> <jta-data-source>java:/BOOKMSSQLDS</jta-data-source> <properties> <property name=”hibernate.dialect” value=”org.hibernate.dialect.SQLServerDialect” /> <property name=”hibernate.hbm2ddl.auto” value=”update” /> </properties> </persistence-unit> </persistence> |
trong đó <jta-data-source>java:/BOOKMSSQLDS</jta-data-source> là datasource bạn cấu hình trong jboss (thay đổi nội dung file mssql-ds.xml trong %JBOSS_HOME%\server\default\deploy\, thêm vào phân đoạn
<local-tx-datasource> <jndi-name>BOOKMSSQLDS</jndi-name> <connection-url> jdbc:sqlserver://localhost:1433;databaseName=BookMS </connection-url> <driver-class> com.microsoft.sqlserver.jdbc.SQLServerDriver </driver-class> <user-name>sa</user-name> <password></password> <metadata> <type-mapping>MS SQLSERVER2000</type-mapping> </metadata> </local-tx-datasource> |
).
5. Tạo Session-Bean
Tạo package vovanhai.wordpress.sessionbean, ta sẽ viết các session bean trong package này.
Với Entity Publisher, ta sẽ tạo session bean như sau:
Tạo interface PublisherDAO.java với nội dung như sau
package vovanhai.wordpress.jpa;
import java.util.Collection; @Remote |
Tạo bean PublisherDAOBean.java có nội dung sau
package vovanhai.wordpress.jpa;
import java.util.Collection; @Stateless @PersistenceContext (name=”FirstJPAProject”) @Override @Override @SuppressWarnings(“all”) @Override |
Tương tự ta tạo các sessonbean cho Book và Booktype entities
BookTypeDAO.java
package vovanhai.wordpress.jpa;
import java.util.Collection; @Remote |
BookTypeDAOBea.java
package vovanhai.wordpress.jpa;
import java.util.Collection; @Stateless @PersistenceContext (name=”FirstJPAProject”) @Override @Override @SuppressWarnings(“all”) |
BookDAO.java
package vovanhai.wordpress.jpa;
import java.util.Collection; @Remote |
BookDAOBean.java
package vovanhai.wordpress.jpa;
import java.util.Collection; @Stateless @Override @Override @SuppressWarnings(“all”) } |
7. Tạo client để thử
package vovanhai.wordpress.jpa;
import java.util.Set; public class Client { InitialContext context=new InitialContext(); Book b=new Book(); Publisher pub=pubdao.findPublisherByID(1); Booktype type=btdao.findBookTypeByID(3); //Search System.out.print(“====================List books by Publisher:”); |
Kết quả hiển thị như sau:
Insert Học java bằng ví dụ completed… Search: JavaServer Faces ====================List books by Publisher:Deiteil================= Tomorow Never Die Chuyện tình Học java bằng ví dụ Tomorow Never Die ====================List books by type:Text Book==================== JavaServer Faces Học java bằng ví dụ Mastering JavaServer Faces |
Chúc các bạn thành công!
lân said
Lần đàu ghé vào đây…quả nhiên là 1 trang web bổ ích…Cám ơn bạn nhiều.
T.Tâm said
Đoạn code chỗ lookup:
InitialContext context=new InitialContext();
BookDAO dao=(BookDAO)context.lookup(”BookDAOBean/remote”);
BookTypeDAO btdao=(BookTypeDAO)context.lookup(”BookTypeDAOBean/remote”);
PublisherDAO pubdao=(PublisherDAO)context.lookup(”PublisherDAOBean/remote”);
Tại sao ta không bắt đầu như sau: initialContext.lookup(“java:comp/env”)
Có sự khác biệt nào nếu có và không có java:comp/env
Mong nhận được phản hồi từ thầy.
Quốc Khánh said
Trong file Bean dòng này hình như không đúng
@PersistenceContext (name=”FirstJPAProject”)
cái này không thấy trong persistence.xml.
Đáng lẽ phải là
@PersistenceContext (unitName=”EbookMS_JPA”)
HipSiGa said
EM lam theo demo nay cua thay trong eclipse
Eclipse Hellios
Oracle Home 9i
JDK 1.6
Jboss 4.2.2 GA
No bi loi “Souce not found” khi chay debug, mong thay giup em sua? a.
Tran Trong Duc
thanh said
em bi bao loi nay :
ids for this class must be manually assigned before calling save()
thay chi giup em.
Võ Văn Hải said
Annotation bạn gắn cho cái ID có chắc là tự sinh không? kiểm tra lại thử!
Huy said
Em đang làm project HK 4 bằng EJB 3, em hay gặp lỗi could not load an entity khi em sử dụng 1 câu lênh select sản phẩm ra, em có kèm theo link hình
Nếu em select tất cả Complaint thì nó lại báo lỗi ‘could not load an entity Account’, em nghỉ là do 2 bảng khóa ngoại Role và Department, khi em xóa 2 bảng đó đi thì chạy không bị lỗi nữa, em không hiểu relationship giữa các bảng này như thế nào trong EJB3, em không biết thầy có bị lỗi này chưa, nhưng em rất mong thầy có thể giải thích cho em về lỗi could not load an entity
Huy said
Em xài SQL 2008 thì MS SQLSERVER2000 em sửa như thế nào hả thầy
thomas80phu said
Nhờ Anh giải giúp bài này
For the following projects, an APDU is defined as:
class APDU {
private byte[] buffer;
public byte[] getBuffer();
public void setBuffer();
}
VirtualSmartCard Server (Java)
Here we just want you to create a simple Java web service using standard technologies.
The environment is:
– JAX-WS 2.0 and EJB 3 annotations to create the web service
– Deploy in JBoss
– Build using Maven2
– Persist objects to the database using JPA2
The service should be called VirtualSmartCard and it should have a single method:
– public APDU transmit(APDU apdu)
transmit() should:
– log the contents of the “apdu” parameter using log4j
– save the APDU structure to a database using JPA2
You should test this using SoapUI.
Võ Văn Hải said
cái này tốn thời gian nhiều. mình đang bận lắm. Bạn nào giúp được không?
nguyenvanquan said
Ai có thể giúp mình vấn đề này được không?
Mình dùng netbean 6.1 server glassfish v2 mình tạo 1 cái modul EJB sau đó tạo CMP Bean.
mình có bảng Sale(slNo, prodID) có khóa ngoại đến Product(prodID,proName)
ở đây mình muốn hỏi truy vấn EJB Query để lấy dữ liệu của cả 2 bảng(Sale và Product)
mình có dùng thử truy vấn : SELECT OBJECT(o) FROM Sale o, Product p
nhưng khi chạy nó báo lỗi cột không hợp lệ PRODUCT_PRODID
sau đó mình dùng truy vấn : SELECT OBJECT(o) FROM Sale o, IN(o.prodID) p
thì nó lại báo lỗi : Field ‘prodID’ of type ‘Product’ is not a collection valued cmr-field.
mình không biết sửa thế nào, mong bạn nào biết thì giúp mình với,
bạn nào sửa được thì có thể gửi qua gmail của mình : nguyenvanquan8990@gmail.com
cám ơn nhiều.
nguyenvanquan said
Ai có thể giúp mình vấn đề này được không ?
Mình dùng netbean 6.1 server glassfish v2 mình tạo 1 cái modul EJB sau đó tạo CMP Bean.
mình có bảng Sale(slNo, prodID) có khóa ngoại đến Product(prodID,proName)
ở đây mình muốn hỏi truy vấn EJB Query để lấy dữ liệu của cả 2 bảng(Sale và Product)
mình có dùng thử truy vấn : SELECT OBJECT(o) FROM Sale o, Product p
nhưng khi chạy nó báo lỗi cột không hợp lệ PRODUCT_PRODID
sau đó mình dùng truy vấn : SELECT OBJECT(o) FROM Sale o, IN(o.prodID) p
thì nó lại báo lỗi : Field ‘prodID’ of type ‘Product’ is not a collection valued cmr-field.
mình không biết sửa thế nào, mong bạn nào biết thì giúp mình với,
bạn nào sửa được thì có thể gửi qua gmail của mình : nguyenvanquan8990@gmail.com
cám ơn nhiều.