`
hsyzijvaa
  • 浏览: 113448 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论
阅读更多



JPA 应用技巧 1:实体类和实体 DAO 模板

Posted on 2011-09-07 17:40 蜀山兆孨龘 阅读(1512) 评论(8)  编辑  收藏  所属分类: Java EE






    最近闲来无事(楼主确实太懒了),重翻旧账,捣鼓了下 JPA 2.0,通过不断地写代码和谷歌,又有了一些旧瓶装新酒的发现和吐槽。楼主将在这一系列文章中慢慢道来。本次开篇带来的是两个模板类:用作实体类基础框架的 AbstractEntity, 以及实现了对实体的基本 CRUD 操作的 BasicEntityDao。
    一个实体类必须实现 java.io.Serializable 接口,必须有一个 ID 字段作为主键,且最好覆盖 equals 和 hashCode 方法。因为实体类和数据表有对应关系,所以往往根据 ID 来实现 equals 和 hashCode。这很自然地可以引出一个模板类,所有的实体类都可以从它继承:
   
        /**
         * 该类可作为实体类的模板,其 {@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";
            }

            /**
             * 返回用于数据库操作的 {&#64;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 就可以简单地写成:
   
        &#64;Stateless
        public class CoopDao extends BasicEntityDao<Coop> {
            &#64;Persistence
            private EntityManager em;

            public CoopDao() {
                super(Coop.class);
            }

            &#64;Override
            protected EntityManager getEntityManager() {
                return em;
            }

            // 更多方法……
        }
   

0
1
分享到:
评论

相关推荐

    实体类生成器

    6. **其他功能**:高级的实体类生成器可能还包括代码格式化、重命名规则、多数据库支持、生成DAO和Service层代码等功能。 7. **使用方式**:实体类生成器可以是命令行工具、IDE插件或者Web服务的形式,开发者输入...

    JPA+spring3+tile集成项目模板。

    在这个项目中,源代码可能包括了Spring的配置文件(如`applicationContext.xml`)、JPA的实体类、以及使用Tiles定义的视图组件。 **集成要点:** 1. **JPA集成**:在Spring配置文件中,需要配置JPA的...

    myeclipse 自动生成DAO层,实体类,mybatis 实体映射文件

    在实际开发中,使用MyEclipse或其他类似工具自动生成DAO层、实体类和映射文件有以下优势: 1. 提高开发效率:避免了手动编写重复的模板代码,使开发者能够更快地完成基础架构。 2. 减少错误:由工具自动生成的代码...

    oracle实体类代码生成器

    5. **注释和序列化支持**:为了提高代码可读性和与其他框架的兼容性,生成的实体类可能还包括JPA的注解(如@Entity、@Id等)和Java Serializable接口。 6. **文件输出**:最后,工具将生成的实体类代码保存到指定的...

    Spring Data JPA 2.0 标准模板

    使用JPA,我们需要定义实体类(Entity),它们映射到数据库表。例如,一个名为`User`的实体: ```java @Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id;...

    手动创建 SpringMvc +SpringDataJpa+Hibernate+ freemarker mavenProject+ 环境切换 webDemo

    4. 数据库实体类:使用Hibernate注解,如@Entity、@Table等,与数据库表进行映射。 5. JpaRepository接口:定义数据库操作,Spring Data JPA会自动生成实现。 6. Service层接口及实现:业务逻辑处理,调用Jpa...

    实体类生成器源码实体类生成器源码

    在Java开发中,实体类是数据访问层(DAO)和业务逻辑层(Service)之间的重要桥梁,它们代表了数据库中的表或者记录。实体类生成器源码的目的是提高开发效率,避免手动编写重复的getter、setter、构造函数以及equals...

    Struts2+Spring+JPA实例

    JPA的配置则通常在persistence.xml文件中,这里会定义实体类和数据源等信息。 在实际操作中,首先需要添加相应的依赖库,包括Struts2、Spring、Hibernate(JPA的实现)以及其他必要的库。在项目结构中,可能有一个...

    springboot-jpa加上jdbctemple

    标题“springboot-jpa加上jdbctemple”指的是在Spring Boot项目中同时使用JPA(Java Persistence API)和JdbcTemplate的技术整合。这是一个常见的后端开发场景,涉及到Spring Boot的数据库访问层的构建,旨在提供...

    velocity spring jpa hibernate 整合

    - 定义JPA实体类,并使用Hibernate的注解进行映射。 - 创建Spring的DAO或Repository接口,利用JPA的Query方法进行数据查询。 - 在Velocity模板中,通过Spring的Model传递数据,生成动态内容。 这样的整合使得开发者...

    Struts2+JPA+Spring整合(PPT)

    使用JPA的注解(如@Entity、@Table、@Id等)来定义实体类,并配置ORM映射。 4. **拦截器配置**:可以利用Spring的AOP功能,为Struts2添加自定义拦截器,实现业务逻辑的预处理和后处理。 5. **测试与优化**:完成...

    spring2.5+jpa

    标题“spring2.5+jpa”表明我们正在讨论一个关于Spring框架2.5版本...压缩包中的“jpa-me-blank”可能是项目的基础结构或模板,可能包含配置文件、实体类、DAO接口等,进一步研究这个文件将有助于理解实际的项目设置。

    SpringBoot使用Spring-data-jpa简化数据访问层

    由于模板Dao的实现,使得这些具体实体的Dao层已经变的非常“薄”,有一些具体实体的Dao实现可能完全就是对模板Dao的简单代理,并且往往这样的实现类可能会出现在很多实体上。Spring-data-jpa的出现正可以让这样一个...

    jpa学习笔记

    JPA 规范定义了一系列接口和注解,用于描述实体类与数据库表之间的映射关系,并提供了基本的数据访问功能。 #### 二、JPA 相关库介绍 为了开发基于 JPA 的应用程序,我们需要依赖一系列的库文件。下面详细介绍这些...

    springboot+data-jpa+thymeleaf简单demo

    1. **实体类(Entity)**:DEMO中应该有一个名为`User`的实体类,它包含了用户的基本信息,如ID、用户名、密码等属性,并使用JPA的注解(如`@Entity`, `@Id`, `@GeneratedValue`等)进行标记。 2. **Repository接口...

    Struts 2 + Spring 2 + JPA + AJAX 示例

    2. **JPA 配置**:设置 JPA 的实体类,定义数据模型,并配置 persistence.xml 文件来指定数据源、实体类和持久化单元。可能还涉及事务策略的设定,如使用 Spring 的 PlatformTransactionManager。 3. **DAO 和 ...

    Spring+JPA+Struts1的整合

    开发者可以使用注解或XML配置来定义实体类,JPA会自动处理SQL查询、事务管理和对象状态管理。 **Struts1框架** Struts1是最早的MVC(模型-视图-控制器)框架之一,用于构建Web应用程序。它将业务逻辑、表示层和控制...

    spring boot+jpa+sqlserver+bootstrap

    2. **定义实体类** 使用JPA注解(例如@Entity、@Table、@Id等)创建Java对象,这些对象将映射到SQL Server的表。 3. **配置JPA** 在Spring Boot的配置类中,可以自定义JPA配置,如实体扫描路径、事务管理器等。 ...

    springjpa 和 spring多视图配置实例

    3. 实体类(Entity)将对应数据库表,用于持久化数据。 4. Repository接口将继承自Spring Data JPA提供的基类,如`JpaRepository`,并可能包含自定义查询方法。 5. Service层将调用Repository接口,处理业务逻辑。 6...

    Spring + JPA + Hibernate配置

    此外,可能还需要编写DAO接口和实现类,使用JPA或Hibernate的API进行数据操作。 通过这篇博文链接(虽然此处未给出实际链接),开发者可以学习到如何将这三个框架集成到一个项目中,包括如何设置相应的Maven或...

Global site tag (gtag.js) - Google Analytics