JPA封装介绍

参考

flea-frame-db使用之封装JPA操作数据库 源代码

依赖

mysql-connector-java-5.1.25.jar

<!-- 数据库JDBC连接相关 (MySQL的JDBC驱动)--><dependency>    <groupId>mysql</groupId>    <artifactId>mysql-connector-java</artifactId>    <version>5.1.25</version></dependency>

eclipselink-2.5.0.jar

<!-- 数据库持久化相关 EclipseLink--><dependency>    <groupId>org.eclipse.persistence</groupId>    <artifactId>eclipselink</artifactId>    <version>2.5.0</version></dependency>

内容讲解

目前支持 JPA + MySQL模式,需要各位本地自行装下MySQL数据库。

1. Flea JPA查询对象

该类用于实现JPA 标准化方式的数据库查询操作,可以自行组装查询条件。相关代码详细可至该路径查看 FleaJPAQuery,下面对一些关键点进行讲解,且听我细细道来 (这一版并发环境下 可能存在问题,后面我会专门写一篇博文讲解 Flea JPA查询对象的问题,其中引入了对象池的概念 )。

  • 获取FleaJPAQuery实例,并初始化内部成员变量

        private static volatile FleaJPAQuery query;    private EntityManager entityManager; // JPA中用于增删改查的持久化接口    private Class sourceClazz; // 实体类类对象    private Class resultClazz; // 操作结果类类对象    private Root root; // 根SQL表达式对象    private CriteriaBuilder criteriaBuilder; //标准化生成器    private CriteriaQuery criteriaQuery; // 标准化查询对象    private List<Predicate> predicates; // Where条件集合    private List<Order> orders; // 排序集合    private List<Expression> groups; // 分组集合    private FleaJPAQuery() {    }    /**     * <p> 获取Flea JPA查询对象 </p>     * (单例模式,本身没有问题,但是由于获取之后Flea JPA查询对象还要使用,     * 这在有点并发的环境下就存在问题了;后面我会单独写一篇博文讲解基于对象池     * 的多例模式,既保证并发下各个线程获取的Flea JPA查询对象之间互不影响,     * 同时也能保证尽可能少的新建Flea JPA查询对象)      *     * @return Flea JPA查询对象     * @since 1.0.0     */    public static FleaJPAQuery getQuery() {        if (ObjectUtils.isEmpty(query)) {            synchronized (FleaJPAQuery.class) {                if (ObjectUtils.isEmpty(query)) {                    query = new FleaJPAQuery();                }            }        }        return query;    }    /**     * <p> getQuery()之后,一定要调用该方法进行初始化 </p>     *     * @param entityManager JPA中用于增删改查的持久化接口     * @param sourceClazz   实体类类对象     * @param resultClazz   操作结果类类对象     * @since 1.0.0     */    public void init(EntityManager entityManager, Class sourceClazz, Class resultClazz) {        this.entityManager = entityManager;        this.sourceClazz = sourceClazz;        this.resultClazz = resultClazz;        // 从持久化接口中获取标准化生成器        criteriaBuilder = entityManager.getCriteriaBuilder();        // 通过标准化生成器 获取 标准化查询对象        if (ObjectUtils.isEmpty(resultClazz)) {            // 行记录查询结果            criteriaQuery = criteriaBuilder.createQuery(sourceClazz);        } else {            // 单个查询结果            criteriaQuery = criteriaBuilder.createQuery(resultClazz);        }        // 通过标准化查询对象,获取根SQL表达式对象        root = criteriaQuery.from(sourceClazz);        predicates = new ArrayList<Predicate>();    }
  • 拼接查询条件,添加排序和分组

        // 等于条件 (单个属性列)    public void equal(String attrName, Object value) throws DaoException;    // 等于条件 (多个属性列)    public void equal(Map<String, Object> paramMap) throws DaoException;    // 不等于条件 (单个属性列)    public void notEqual(String attrName, Object value) throws DaoException;    // 等于条件 (多个属性列)    public void notEqual(Map<String, Object> paramMap) throws DaoException;    // is null 条件,某属性值为空    public void isNull(String attrName) throws DaoException;    // is not null 条件,某属性值为非空    public void isNotNull(String attrName) throws DaoException;    // in 条件, attrName属性的值在value集合中    public void in(String attrName, Collection value) throws DaoException;    //  not in 条件,attrName属性的值不在value集合中    public void notIn(String attrName, Collection value) throws DaoException;    // like 条件, 模糊匹配    public void like(String attrName, String value) throws DaoException;    // 小于等于条件    public void le(String attrName, Number value) throws DaoException;    // 小于条件    public void lt(String attrName, Number value) throws DaoException;    // 大于等于条件    public void ge(String attrName, Number value) throws DaoException;    // 大于条件    public void gt(String attrName, Number value) throws DaoException;    // between and 条件, 时间区间查询    public void between(String attrName, Date startTime, Date endTime) throws DaoException;    // 大于某个日期值条件    public void greaterThan(String attrName, Date value) throws DaoException;    // 大于等于某个日期值条件    public void greaterThanOrEqualTo(String attrName, Date value) throws DaoException;    // 小于某个日期值条件    public void lessThan(String attrName, Date value) throws DaoException;    // 小于等于某个日期值条件    public void lessThanOrEqualTo(String attrName, Date value) throws DaoException;    // 统计数目,在getSingleResult调用之前使用    public void count();    // 统计数目(带distinct参数),在getSingleResult调用之前使用    public void countDistinct();    // 设置查询某属性的最大值,在getSingleResult调用之前使用    public void max(String attrName) throws DaoException;    // 设置查询某属性的最小值,在getSingleResult调用之前使用    public void min(String attrName) throws DaoException;    // 设置查询某属性的平均值,在getSingleResult调用之前使用    public void avg(String attrName) throws DaoException;    // 设置查询某属性的值的总和,在getSingleResult调用之前使用    public void sum(String attrName) throws DaoException;    // 设置查询某属性的值的总和(Long),在getSingleResult调用之前使用    public void sumAsLong(String attrName) throws DaoException;    // 设置查询某属性的值的总和(Double),在getSingleResult调用之前使用    public void sumAsDouble(String attrName) throws DaoException;    // 去重某一列    public void distinct(String attrName) throws DaoException;    // 添加order by子句    public void addOrderby(String attrName, String orderBy) throws DaoException;    // 添加group by子句    public void addGroupBy(String attrName) throws DaoException;
  • 获取查询结果(记录行 或 单个结果)
    // 获取查询的记录行结果集合    public List getResultList() throws DaoException;    // 获取查询的记录行结果集合(设置查询范围)    public List getResultList(int start, int max) throws DaoException;    // 获取查询的单个属性列结果集合    // 需要先调用 distinct,否则默认返回行记录结果集合    public List getSingleResultList() throws DaoException;    // 获取查询的单个属性列结果集合(设置查询范围,可用于分页)    // 需要先调用 distinct,否则默认返回行记录结果集合    public List getSingleResultList(int start, int max) throws DaoException;    // 获取查询的单个结果    // 需要提前调用 (count, countDistinct, max, min, avg, sum, sumAsLong, sumAsDouble)    public Object getSingleResult() throws DaoException;

    2. 数据处理的基本接口

    基本的数据操作接口,其中包含了查询,(批量)添加,(批量)更新,删除等操作,详细可至GitHub查看 IFleaJPABaseDataHandler。

    3. 抽象Flea JPA DAO层接口

/** * <p> 抽象Flea JPA DAO层接口,实现基本的查询、(批量)添加、(批量)更新、删除接口 </p> * * @author huazie * @version 1.0.0 * @since 1.0.0 */public interface IAbstractFleaJPADAO<T> extends IFleaJPABaseDataHandler<T> {}

4. 抽象Flea JPA DAO层实现

本类中实现上述3中查询、(批量)添加、(批量)更新、删除的接口的具体逻辑,详细可至GitHub查看 AbstractFleaJPADAOImpl。

  • 该类实现上述抽象Flea JPA DAO层接口,同样有类型T,由子类指定其操作的实体类。
    public abstract class AbstractFleaJPADAOImpl<T> implements IAbstractFleaJPADAO<T> 
  • 无参构造方法,用于获取子类指定的实体类类对象。

    /** * <p> 获取T类型的Class对象 </p> * * @since 1.0.0 */public AbstractFleaJPADAOImpl() {    // 获取泛型类的子类对象的Class对象    Class<?> clz = getClass();    // 获取子类对象的泛型父类类型(也就是AbstractDaoImpl<T>)    ParameterizedType type = (ParameterizedType) clz.getGenericSuperclass();    if (LOGGER.isDebugEnabled()) {        LOGGER.debug("Type={}", type);    }    Type[] types = type.getActualTypeArguments();    clazz = (Class<T>) types[0];    if (LOGGER.isDebugEnabled()) {        LOGGER.debug("ClassName={}", clazz.getName());    }}
  • 实现接口方法,可参见上述类源码
  • 持久化接口获取,由子类实现(可参考下面的持久化单元DAO层实现)

    /** * <p> 获取EntityManager对象 </p> * * @return EntityManager对象 * @since 1.0.0 */protected abstract EntityManager getEntityManager();
  • Flea JPA查询对象获取

    /** * <p> 获取指定的查询对象 </p> * <p> 上一个版本如下调用,基于对象池的多例模式之后,获取Flea JPA查询对象有不同,可参考源码 </p> * * @return 自定义Flea JPA查询对象 * @since 1.0.0 */protected FleaJPAQuery getQuery(Class result) {    // 获取Flea JPA查询对象实例    FleaJPAQuery query = FleaJPAQuery.getQuery();    // 获取实例后必须调用该方法进行初始化    query.init(getEntityManager(), clazz, result);    return query;}

    5. 定义抽象Flea JPA SV层接口

/** * <p> 抽象Flea JPA SV层接口 </p> * * @author huazie * @version 1.0.0 * @since 1.0.0 */public interface IAbstractFleaJPASV<T> extends IFleaJPABaseDataHandler<T> {}

6. 抽象Flea JPA SV层实现

该类实现上述抽象Flea JPA SV层接口,相关代码也比较简单,具体接口实现内部调用抽象Flea JPA DAO层实现,详细可至GitHub查看 AbstractFleaJPASVImpl,如下举例:

    @Override    public T query(long entityId) throws Exception {        return getDAO().query(entityId);    }    // ... 其他接口实现已省略    /**     * <p> 获取Flea JPA DAO层实现 </p>     *     * @return 抽象Flea JPA DAO层实现     * @since 1.0.0     */    protected abstract IAbstractFleaJPADAO<T> getDAO();

7. 持久化单元DAO层实现

该类与持久化单元一一对应,如果新增一个持久化配置,即需要新增一个持久化单元DAO层实现,同时Spring配置中,需要加入对应的持久化单元事物管理者配置。详细可至GitHub查看 FleaAuthDAOImpl

  • 持久化单元名 ----- fleaauth
  • 持久化事物管理者 ----- fleaauthTransactionManager
  • 持久化接口对象 ----- entityManager (该类由注解定义,由Spring配置中的 持久化接口工厂 fleaAuthEntityManagerFactory 初始化,详细可见下面持久化单元相关配置)
/** * <p> FleaAuth数据源DAO层父类 </p> * * @author huazie * @version 1.0.0 * @since 1.0.0 */public class FleaAuthDAOImpl<T> extends AbstractFleaJPADAOImpl<T> {    @PersistenceContext(unitName="fleaauth")    protected EntityManager entityManager;    @Override    @Transactional("fleaAuthTransactionManager")    public boolean remove(long entityId) throws Exception {        return super.remove(entityId);    }    // 其余代码省略。。。    @Override    protected EntityManager getEntityManager() {        return entityManager;    }}

8. 配置介绍

  • 持久化单元配置 fleaauth-persistence.xml

    <?xml version="1.0" encoding="UTF-8"?><persistence version="2.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_2_0.xsd">    <persistence-unit name="fleaauth" transaction-type="RESOURCE_LOCAL">        <!-- provider -->        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>        <!-- Connection JDBC -->        <class>具体实体类全名</class>        <exclude-unlisted-classes>true</exclude-unlisted-classes>        <properties>            <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/fleaauth?useUnicode=true&characterEncoding=UTF-8" />            <property name="javax.persistence.jdbc.user" value="root" />            <property name="javax.persistence.jdbc.password" value="root" />        </properties>    </persistence-unit></persistence>
  • Spring配置

        <!-- 持久化单元管理器 -->    <bean id="defaultPersistenceManager" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">        <property name="persistenceXmlLocations">            <!-- 可以配置多个持久单元 -->            <list>                <value>classpath:META-INF/fleaauth-persistence.xml</value>            </list>        </property>    </bean>    <!-- 持久化提供者 -->    <bean id="defaultPersistenceProvider" class="org.eclipse.persistence.jpa.PersistenceProvider"/>    <!-- 加载时织入器 -->    <bean id="defaultLoadTimeWeaver" class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>    <!-- JPA厂商适配器,对外公开EclipseLink的持久性提供程序和EntityManager扩展接口  -->    <bean id="defaultVendorAdapter" class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">        <!-- 是否在控制台显示sql -->        <property name="showSql" value="true"/>    </bean>    <!-- JpaDialect EclipseLink持久化服务的实现-->    <bean id="defaultJpaDialect" class="org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect"/>    <!-- 以下部分 与指定持久化单元一一对应 -->    <!-- ################################## -->    <!-- FleaAuth TransAction Manager JPA -->    <!-- ################################## -->    <bean id="fleaAuthEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">        <property name="persistenceUnitManager" ref="defaultPersistenceManager"/>        <property name="persistenceUnitName" value="fleaauth"/>        <property name="persistenceProvider" ref="defaultPersistenceProvider"/>        <property name="jpaVendorAdapter" ref="defaultVendorAdapter"/>        <property name="jpaDialect" ref="defaultJpaDialect"/>        <property name="jpaPropertyMap">            <map>                <entry key="eclipselink.weaving" value="false"/>            </map>        </property>    </bean>    <bean id="fleaAuthTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">        <property name="entityManagerFactory" ref="fleaAuthEntityManagerFactory"/>    </bean>    <tx:annotation-driven transaction-manager="fleaAuthTransactionManager"/>

    至此,相关JPA使用已封装完毕,下一篇博文将介绍 JPA接入,敬请期待。

©著作权归作者所有:来自51CTO博客作者Huazie的原创作品,如需转载,请注明出处,否则将追究法律责任

好知识,才能预见未来

赞赏

0人进行了赞赏支持

更多相关文章

  1. iOS逆向与安全
  2. 算法训练营
  3. PyTorch入门到进阶 实战计算机视觉与自然语言处理项目
  4. mysql数据库CURD中常用操作
  5. 用grid仿php.cn首页,grid实现媒体查询
  6. JavaScript对象与其复制清除方法简析
  7. 不知道JVM逃逸分析?看这篇文章就够了!
  8. 你真的会写java吗?
  9. 3-24(类与对象的自我总结)

随机推荐

  1. android ImageView 显示本地图片
  2. android屏幕截图
  3. 【Android】Face Recognition on Android
  4. android技术文章网址
  5. Android TabHost详解
  6. Android7.0中文文档(API)-- ZoomButtonsCon
  7. Android API与Android版本的关系
  8. Android RecyclerView ItemDecoration ti
  9. Android,WiFi连接eap
  10. android中ui添加水平线