2016年10月21日 星期五

ejb 3 local

一樣是參照
http://theopentutorials.com/examples/java-ee/ejb3/how-to-create-ejb3-jpa-project-in-eclipse-jboss-as-6-1/

延續上篇~上篇是搞定 JNDI
這邊是建個簡單的 EJB...

差別就是,這邊先使用簡單的 Local ,所以有改寫 client 取的來源,還有一些其他的筆記~

6. 設定 persistence.xml
環境設定一直都是個惡夢...雖然久久一次(通常也是只建那麼一次...),但是每次都會出槌Orz...
classes/META-INF/persistence.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
    <persistence-unit name="mypersistence" transaction-type="JTA">
        <jta-data-source>java:jboss/datasources/PostgresDS</jta-data-source>
        <properties>
            <property name="showSql" value="true"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />
        </properties>
    </persistence-unit>
</persistence>

重點就是,EJB 通常是個 jar/ear 檔,所以這個檔的位置是放在 classes/META-INF 裡面的~~如果想放在 war 裡面的話,就是自己手動 copy 到 webapp/WEB-INF/classes/META-INF/persistence.xml 裡面~~放錯位置,就會一直找不到Orz..

至於因為是用 JBoss ,內建 hibernate ,所以沒設定,就是默認為 hibernate 的 jpa..hibernate 設定大概就是要依DB定 hibernate.dialect

7.  Entity
對應 DB 的 Enitity Bean..現在有 annotation 就方便很多~
因為是用 hibernate,也等同 hibernate 的  O/R mapping
(大概就是 pojo,  bo(business object),印象中就是  EJB 概念中有比較活在潮流裡的項目,不過是因為 hibernate 發揚光大的...但真心的說,身為 SQL 派的我討厭hibernate..)

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Column;

@Entity(name = "yyy")
public class AAAA implements Serializable {
    private static final long serialVersionUID = 1L;
   
    public AAAA()  {
        super();
    }
   
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator="yyy_id_seq")
    @SequenceGenerator(name="yyy_id_seq", sequenceName="yyy_id_seq", allocationSize=1)
    @Column(name = "id")
    private Long id;
   
    @Column(name = "name")
    private String complete;


Postgresql 如果用 SERIAL 當 type ,其實是個 seq,就設定上要再訂一下。

8. Business Interface
這邊有分 Local 和  Remote,因為 Local 比較簡單,反正之後也是用這個...就先用 Local...
(這層就差不多是 spring 的 service 層(interface))

import javax.ejb.Local;

@Local
public interface  AAAAService {
    /**
     * query all
     * @return all data
     */
    public List<AAAA> findAll();
   
    /**
     * insert
     * @param data
     */
    public void insert(AAAA data);
  
9. Business Logic
實做 business interface...在這邊連結 persistence 的設定,EJB 在這裡可以就下 sql 直接 access db 了
(就也是spring 的 serviceImp,至於底下要不要多一層 dao,看人看架構吧。)

另外因為是套用 hibernate ,所以就要用 hsql 下(個人覺得也是惡夢 Orz)

import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

@Stateless
public class AAAAServiceBean implements AAAAService {
   
    @PersistenceContext(unitName = "mypersistence")
    private EntityManager entityManager;
    
    public AAAAServiceBean() {  
    }
   
    /**
     * query all
     * @return all data
     */
    public List<AAAA> findAll()  {
        String q = "FROM "+AAAA.class.getName();
        Query query = entityManager.createQuery(q);
        List<AAAA> lst = query.getResultList();
        return lst;
    }

   /**
     * search data according to keyword
     * @param keyword for search
     * @return list of data
     */
    public List<AAAA> search(String keyword)  {
        if(keyword == null || keyword.trim().length() == 0)  {
            return findAll();
        }
        String q = "FROM "+AAAA.class.getName()+" t WHERE t.name LIKE :keyword";
        Query query = entityManager.createQuery(q).setParameter("name", keyword);
        List<AAAA> lst = query.getResultList();
        return lst;
    }
   
    /**
     * insert
     * @param data
     */
    public void insert(AAAA data)  {
        entityManager.persist(data);
    }
   
    /**
     * update data by key (id)
     * @param data
     */
    public void update(AAAA data)  {
        entityManager.merge(data);
    }
   
    /**
     * delete data by key (id)
     * @param data
     */
    public void delete(AAAA data)  {
        entityManager.remove(data);
    }

10. Client
在 EJB 會弄個 Client 來呼叫 Bussiness,基本上也只是去查 Context Name 弄出來
(spring 是把 service 做成 spring 的 bean 來注入,EJB 就得自己去  lookup...所以要知道 service 叫什麼名字是很重要的~那個 cli 指令就還蠻好用的)

client 就沒有什麼特別的 annotation..重點只是在怎麼拿到 Bussiness Instance

Context initContext = new InitialContext();
Context ctx = (Context) initContext.lookup("java:app/MYWEBAPP");
AAAService bean = (AAAService) context.lookup("AAAServiceBean");
List<AAA> list = bean.findAll();
bean.insert(....);

貼一下,如果在 cli 看到的 ServiceBean 大概就會長這樣子
(其實在 context naming 裡,很多 scope 都會有,只是我想就用 app,自己範圍的就好)
"applications" => {"MYWEBAPP.war" => {
    "java:app" => {
    ...
    "MYWEBAPP" => {
    "class-name" => "javax.naming.Context",
    "children" => {
    ...
        "AAAAServiceBean" => {
        "class-name" => "xxx.yyy.businesslogic.AAAAServiceBean",
        "value" => "?"
        },
    ...

在這邊也可以看一下 serviceBean 有沒有被正確的放進來,然後就可以連線測試了~

沒有留言: