<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 :: 首頁(yè) ::  :: 聯(lián)系 :: 聚合  :: 管理

    最近閑來(lái)無(wú)事(樓主確實(shí)太懶了),重翻舊賬,搗鼓了下 JPA 2.0,通過(guò)不斷地寫(xiě)代碼和谷歌,又有了一些舊瓶裝新酒的發(fā)現(xiàn)和吐槽。樓主將在這一系列文章中慢慢道來(lái)。本次開(kāi)篇帶來(lái)的是兩個(gè)模板類:用作實(shí)體類基礎(chǔ)框架的 AbstractEntity, 以及實(shí)現(xiàn)了對(duì)實(shí)體的基本 CRUD 操作的 BasicEntityDao

    一個(gè)實(shí)體類必須實(shí)現(xiàn) java.io.Serializable 接口,必須有一個(gè) ID 字段作為主鍵,且最好覆蓋 equalshashCode 方法。因?yàn)閷?shí)體類和數(shù)據(jù)表有對(duì)應(yīng)關(guān)系,所以往往根據(jù) ID 來(lái)實(shí)現(xiàn) equalshashCode。這很自然地可以引出一個(gè)模板類,所有的實(shí)體類都可以從它繼承:

            /**
             * 該類可作為實(shí)體類的模板,其 {@link #equals(Object)} 和 {@link hashCode()} 方法基于主鍵實(shí)現(xiàn)。
             * 子類只需要實(shí)現(xiàn) {@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());
                }
            }
        

    針對(duì)主鍵的類型,AbstractEntity 可以進(jìn)一步擴(kuò)展。例如,可以擴(kuò)展出一個(gè) UuidEntity,它使用隨機(jī)生成的 UUID 作為主鍵:

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

    繼續(xù)發(fā)揮想象,讓它支持樂(lè)觀鎖:

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

    這兒順便插嘴吐槽下主鍵的類型。用整數(shù)還是 UUID 好呢?這個(gè)問(wèn)題在網(wǎng)上也是爭(zhēng)論紛紛。在樓主看來(lái),兩者各有優(yōu)劣:整數(shù)主鍵性能高,可讀性也好,但會(huì)對(duì)數(shù)據(jù)遷移,例如合并兩個(gè)數(shù)據(jù)庫(kù),造成不小的麻煩,因?yàn)榭赡艹霈F(xiàn)一大堆重復(fù)的主鍵;UUID 性能差些,看起來(lái)晃眼,雖然據(jù)說(shuō)有些數(shù)據(jù)庫(kù)針對(duì)性地做了優(yōu)化,想來(lái)也不大可能優(yōu)于整數(shù),不過(guò)好處就是理論上出現(xiàn)重復(fù)主鍵的概率比中彩票還小(福彩除外)。說(shuō)這么一大堆,其實(shí)還是蠻糾結(jié)啊……樓主一般傾向于用 UUID,只要服務(wù)器的配置夠勁,想來(lái)不會(huì)出現(xiàn)明顯的性能問(wèn)題。

    接下來(lái)說(shuō)說(shuō) BasicEntityDao,它提供了基本的 CRUD 實(shí)現(xiàn),可以用來(lái)為會(huì)話 Bean 做模板:

            /**
             * 提供了對(duì)實(shí)體進(jìn)行基本 CRUD 操作的實(shí)現(xiàn),可作為會(huì)話 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";
                }
    
                /**
                 * 返回用于數(shù)據(jù)庫(kù)操作的 {@link EntityManager} 實(shí)例。
                 */
                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() 的實(shí)現(xiàn)即可。假設(shè)樓主要做一個(gè)養(yǎng)雞場(chǎng)管理系統(tǒng),對(duì)雞圈進(jìn)行操作的會(huì)話 Bean 就可以簡(jiǎn)單地寫(xiě)成:

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

    評(píng)論

    # re: JPA 應(yīng)用技巧 1:介紹 AbstractEntity 和 BasicEntityDao  回復(fù)  更多評(píng)論   

    2011-09-07 19:54 by 來(lái)如風(fēng)
    暈uuid還用這樣搞啊,有很多內(nèi)置的生成器可以了!!!!!!!

    # re: JPA 應(yīng)用技巧 1:介紹 AbstractEntity 和 BasicEntityDao  回復(fù)  更多評(píng)論   

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

    # re: JPA 應(yīng)用技巧 1:實(shí)體類和實(shí)體 DAO 模板  回復(fù)  更多評(píng)論   

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

    # re: JPA 應(yīng)用技巧 1:實(shí)體類和實(shí)體 DAO 模板  回復(fù)  更多評(píng)論   

    2011-09-09 09:49 by 蜀山兆孨龘
    @tb
    有什么質(zhì)疑請(qǐng)說(shuō)出來(lái),咱以理服人好不?

    # re: JPA 應(yīng)用技巧 1:實(shí)體類和實(shí)體 DAO 模板  回復(fù)  更多評(píng)論   

    2011-09-09 23:45 by 來(lái)如風(fēng)
    樓主你看看spring的spring-data工程,你會(huì)發(fā)現(xiàn)dao怎么搞了,

    # re: JPA 應(yīng)用技巧 1:實(shí)體類和實(shí)體 DAO 模板  回復(fù)  更多評(píng)論   

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

    # re: JPA 應(yīng)用技巧 1:實(shí)體類和實(shí)體 DAO 模板  回復(fù)  更多評(píng)論   

    2011-09-10 22:23 by 來(lái)如風(fēng)
    那研究jpa干什么,研究apache dbutil 或者ibatis 就夠了,前兩者完全可以滿足你的需求,在自己在業(yè)務(wù)層加個(gè)緩存,就夠了!!!!!!!!!!

    # re: JPA 應(yīng)用技巧 1:實(shí)體類和實(shí)體 DAO 模板  回復(fù)  更多評(píng)論   

    2011-09-11 19:56 by 蜀山兆孨龘
    @來(lái)如風(fēng)
    既然 JPA 支持 EntityManager#createNativeQuery,為什么不能研究?用 JPA 就非得要和你說(shuō)的那些框架一起用嗎?我這篇文章有什么問(wèn)題請(qǐng)你直接指出來(lái),不要亂扯別的框架好不好?
    主站蜘蛛池模板: 国产啪精品视频网站免费尤物| 亚洲精品乱码久久久久久不卡| 日韩亚洲欧洲在线com91tv| 成年女人A毛片免费视频| 亚洲免费视频一区二区三区| a级毛片免费全部播放| 亚洲视频一区二区在线观看| 免费观看理论片毛片| 成年女人A毛片免费视频| 亚洲五月综合缴情婷婷| 亚洲国产精品无码久久青草| 桃子视频在线观看高清免费视频 | 亚洲高清无码在线观看| 国偷自产一区二区免费视频| 亚洲va久久久久| 麻豆一区二区免费播放网站| 国产亚洲男人的天堂在线观看| 亚洲人成依人成综合网| 国产日产成人免费视频在线观看 | 国产大片线上免费观看| 又粗又长又爽又长黄免费视频| 亚洲春色另类小说| 亚洲一区二区精品视频| 成人无码区免费A片视频WWW | 免费在线观看的网站| 中文字幕在线观看免费| 亚洲人成未满十八禁网站| 亚洲第一精品在线视频| 97在线视频免费播放| 曰批免费视频播放在线看片二| 亚洲国产精品成人综合久久久 | 四虎永久在线精品免费观看视频 | 欧洲黑大粗无码免费| 国产精品偷伦视频观看免费 | 亚洲视频一区网站| 亚洲人成网亚洲欧洲无码久久| 免费看国产曰批40分钟| 午夜宅男在线永久免费观看网| 无码国产精品一区二区免费式芒果| 午夜成人无码福利免费视频| 中国亚洲呦女专区|