<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    神奇好望角 The Magical Cape of Good Hope

    庸人不必自擾,智者何需千慮?
    posts - 26, comments - 50, trackbacks - 0, articles - 11
      BlogJava :: 首頁 ::  :: 聯系 :: 聚合  :: 管理

    JPA 應用技巧 1:實體類和實體 DAO 模板

    Posted on 2011-09-07 17:40 蜀山兆孨龘 閱讀(3568) 評論(8)  編輯  收藏 所屬分類: Java EE

    最近閑來無事(樓主確實太懶了),重翻舊賬,搗鼓了下 JPA 2.0,通過不斷地寫代碼和谷歌,又有了一些舊瓶裝新酒的發現和吐槽。樓主將在這一系列文章中慢慢道來。本次開篇帶來的是兩個模板類:用作實體類基礎框架的 AbstractEntity, 以及實現了對實體的基本 CRUD 操作的 BasicEntityDao

    一個實體類必須實現 java.io.Serializable 接口,必須有一個 ID 字段作為主鍵,且最好覆蓋 equalshashCode 方法。因為實體類和數據表有對應關系,所以往往根據 ID 來實現 equalshashCode。這很自然地可以引出一個模板類,所有的實體類都可以從它繼承:

            /**
             * 該類可作為實體類的模板,其 {@link #equals(Object)} 和 {@link hashCode()} 方法基于主鍵實現。
             * 子類只需要實現 {@link #getId()} 方法。
             */
            public abstract class AbstractEntity implements Serializable {
                /**
                 * 返回主鍵。
                 */
                public abstract Object getId();
    
                @Override
                public boolean equals(Object obj) {
                    if (this == obj) {
                        return true;
                    }
                    if (obj == null || getClass() != obj.getClass()) {
                        return false;
                    }
                    return getId() == null ? false
                            : getId().equals(((AbstractEntity) obj).getId());
                }
    
                @Override
                public int hashCode() {
                    return Objects.hashCode(getId());
                }
            }
        

    針對主鍵的類型,AbstractEntity 可以進一步擴展。例如,可以擴展出一個 UuidEntity,它使用隨機生成的 UUID 作為主鍵:

            @MappedSuperclass
            public class UuidEntity extends AbstractEntity {
                @Id
                private String id;
    
                @Override
                public String getId() {
                    return id;
                }
    
                @PrePersist
                private void generateId() {
                    // 僅在持久化前生成 ID,提升一點性能。
                    id = UUID.randomUUID().toString();
                }
            }
        

    繼續發揮想象,讓它支持樂觀鎖:

            @MappedSuperclass
            public class VersionedUuidEntity extends UuidEntity {
                @Version
                private int version;
            }
        

    這兒順便插嘴吐槽下主鍵的類型。用整數還是 UUID 好呢?這個問題在網上也是爭論紛紛。在樓主看來,兩者各有優劣:整數主鍵性能高,可讀性也好,但會對數據遷移,例如合并兩個數據庫,造成不小的麻煩,因為可能出現一大堆重復的主鍵;UUID 性能差些,看起來晃眼,雖然據說有些數據庫針對性地做了優化,想來也不大可能優于整數,不過好處就是理論上出現重復主鍵的概率比中彩票還小(福彩除外)。說這么一大堆,其實還是蠻糾結啊……樓主一般傾向于用 UUID,只要服務器的配置夠勁,想來不會出現明顯的性能問題。

    接下來說說 BasicEntityDao,它提供了基本的 CRUD 實現,可以用來為會話 Bean 做模板:

            /**
             * 提供了對實體進行基本 CRUD 操作的實現,可作為會話 Bean 的模板。
             */
            public abstract class BasicEntityDao<T> {
                private Class<T> entityClass;
                private String entityClassName;
                private String findAllQuery;
                private String countQuery;
    
                protected BasicEntityDao(Class<T> entityClass) {
                    this.entityClass = Objects.requireNonNull(entityClass);
                    entityClassName = entityClass.getSimpleName();
                    findAllQuery = "select e from " + entityClassName + " e";
                    countQuery = "select count(e) from " + entityClassName + " e";
                }
    
                /**
                 * 返回用于數據庫操作的 {@link EntityManager} 實例。
                 */
                protected abstract EntityManager getEntityManager();
    
                public void persist(T entity) {
                    getEntityManager().persist(entity);
                }
    
                public T find(Object id) {
                    return getEntityManager().find(entityClass, id);
                }
    
                public List<T> findAll() {
                    return getEntityManager().createQuery(findAllQuery, entityClass).getResultList();
                }
    
                public List<T> findRange(int first, int max) {
                    return getEntityManager().createQuery(findAllQuery, entityClass)
                            .setFirstResult(first).setMaxResults(max).getResultList();
                }
    
                public long count() {
                    return (Long) getEntityManager().createQuery(countQuery).getSingleResult();
                }
    
                public T merge(T entity) {
                    return getEntityManager().merge(entity);
                }
    
                public void remove(T entity) {
                    getEntityManager().remove(merge(entity));
                }
            }
        

    子類只需要提供 getEntityManager() 的實現即可。假設樓主要做一個養雞場管理系統,對雞圈進行操作的會話 Bean 就可以簡單地寫成:

            @Stateless
            public class CoopDao extends BasicEntityDao<Coop> {
                @Persistence
                private EntityManager em;
    
                public CoopDao() {
                    super(Coop.class);
                }
    
                @Override
                protected EntityManager getEntityManager() {
                    return em;
                }
    
                // 更多方法……
            }
        

    評論

    # re: JPA 應用技巧 1:介紹 AbstractEntity 和 BasicEntityDao  回復  更多評論   

    2011-09-07 19:54 by 來如風
    暈uuid還用這樣搞啊,有很多內置的生成器可以了!!!!!!!

    # re: JPA 應用技巧 1:介紹 AbstractEntity 和 BasicEntityDao  回復  更多評論   

    2011-09-07 20:47 by 蜀山兆孨龘
    @來如風
    先別忙著暈呵呵。我這兒討論的是 JPA 規范,而目前的最新版 2.0 不支持 UUID 生成,2.1 才有計劃。你一定是用的 Hibernate 之類的專有 API 吧?

    # re: JPA 應用技巧 1:實體類和實體 DAO 模板  回復  更多評論   

    2011-09-09 08:22 by tb
    uuid還有這樣搞得嗎

    # re: JPA 應用技巧 1:實體類和實體 DAO 模板  回復  更多評論   

    2011-09-09 09:49 by 蜀山兆孨龘
    @tb
    有什么質疑請說出來,咱以理服人好不?

    # re: JPA 應用技巧 1:實體類和實體 DAO 模板  回復  更多評論   

    2011-09-09 23:45 by 來如風
    樓主你看看spring的spring-data工程,你會發現dao怎么搞了,

    # re: JPA 應用技巧 1:實體類和實體 DAO 模板  回復  更多評論   

    2011-09-10 00:27 by 蜀山兆孨龘
    @來如風
    我這兒只談 JPA,不涉及 Spring……數據庫訪問這種東西,封裝得越厚,性能降得越恐怖,不信你可以自己去測。功底夠好的話,完全可以直接寫 SQL 查詢語句(EntityManager#createNativeQuery),而只把封裝查詢結果和做緩存的任務交給 JPA。

    # re: JPA 應用技巧 1:實體類和實體 DAO 模板  回復  更多評論   

    2011-09-10 22:23 by 來如風
    那研究jpa干什么,研究apache dbutil 或者ibatis 就夠了,前兩者完全可以滿足你的需求,在自己在業務層加個緩存,就夠了!!!!!!!!!!

    # re: JPA 應用技巧 1:實體類和實體 DAO 模板  回復  更多評論   

    2011-09-11 19:56 by 蜀山兆孨龘
    @來如風
    既然 JPA 支持 EntityManager#createNativeQuery,為什么不能研究?用 JPA 就非得要和你說的那些框架一起用嗎?我這篇文章有什么問題請你直接指出來,不要亂扯別的框架好不好?
    主站蜘蛛池模板: 亚洲人成影院77777| 国产亚洲av片在线观看16女人| 亚洲黄色网址在线观看| 免费在线黄色电影| 奇米影视亚洲春色| 精品一区二区三区高清免费观看| 无码国产亚洲日韩国精品视频一区二区三区| 亚洲第一区二区快射影院| 无码少妇一区二区浪潮免费| 亚洲an日韩专区在线| 在线看片无码永久免费视频| 亚洲日本人成中文字幕| 男女啪啪永久免费观看网站| 亚洲国产成人久久综合| 亚洲丰满熟女一区二区v| 久久国产免费观看精品3| 亚洲精品自在线拍| 特级做A爰片毛片免费69| 狼人大香伊蕉国产WWW亚洲| 亚洲精品国产va在线观看蜜芽| g0g0人体全免费高清大胆视频| 亚洲熟妇无码AV在线播放| 久久青草免费91观看| 亚洲av无码国产综合专区| 国产老女人精品免费视频| japanese色国产在线看免费| 亚洲国产一区二区a毛片| 最新仑乱免费视频| 一区二区三区在线观看免费| 免费成人黄色大片| 久久久久久亚洲Av无码精品专口| 亚洲免费在线视频| 在线永久免费的视频草莓| 亚洲精品无播放器在线播放| 在线观看亚洲免费| 性xxxxx大片免费视频| 亚洲一卡2卡3卡4卡5卡6卡| 中文字幕亚洲综合久久菠萝蜜 | 青青草a免费线观a| 免费又黄又爽又猛大片午夜 | 成年男女男精品免费视频网站|