使用Spring和Java泛型简化数据访问层

1.概述

本文将着重于通过对系统中的所有实体使用单个通用的数据访问对象来简化DAO层 ,这将导致优雅的数据访问 ,而不会造成不必要的混乱或冗长。

2. Hibernate和JPA DAO

大多数生产代码库都有某种DAO层。 通常,实现范围从没有抽象基类的多个类到某种通用类。 但是,一件事是一致的- 总是多于一件事-最有可能的是,DAO与系统中的实体之间存在一对一的关系。

同样,根据所涉及泛型的级别,实际的实现方式可能从大量重复的代码变为几乎为空的代码,大部分逻辑分组在基本抽象类中。

通常,可以通过使用Java Generics提供的类型安全性, 用单个参数化DAO替换这些多个实现,这样就不会损失任何功能。

接下来介绍此概念的两种实现 ,一种用于Hibernate中心持久性层,另一种针对JPA 。 这些实现绝不是完整的-仅包括某些数据访问方法,但是可以很容易地使它们变得更彻底。

2.1。 抽象的休眠DAO

public abstract class AbstractHibernateDao< T extends Serializable > {private Class< T > clazz;@AutowiredSessionFactory sessionFactory;public final void setClazz( Class< T > clazzToSet ){this.clazz = clazzToSet;}public T findOne( long id ){return (T) getCurrentSession().get( clazz, id );}public List< T > findAll(){return getCurrentSession().createQuery( "from " + clazz.getName() ).list();}public void create( T entity ){getCurrentSession().persist( entity );}public void update( T entity ){getCurrentSession().merge( entity );}public void delete( T entity ){getCurrentSession().delete( entity );}public void deleteById( long entityId ){T entity = findOne( entityId );delete( entity );}protected final Session getCurrentSession(){return sessionFactory.getCurrentSession();}
}

DAO直接使用Hibernate API,而不依赖于任何Spring模板(例如HibernateTemplate )。 Hibernate DAO教程介绍了模板的使用以及在DAO中自动装配的SessionFactory的管理。

2.2。 通用休眠DAO

现在已经完成了抽象DAO,我们只需实现一次即可- 通用DAO实现将成为唯一需要的实现

@Repository
@Scope( BeanDefinition.SCOPE_PROTOTYPE )
public class GenericHibernateDao< T extends Serializable >extends AbstractHibernateDao< T > implements IGenericDao< T >{//
}

首先,请注意,通用实现本身参数化的 -允许客户根据具体情况选择正确的参数。 这将意味着客户端将获得类型安全的所有好处,而无需为每个实体创建多个工件。

其次,注意这些通用DAO实现的原型范围 。 使用此范围意味着Spring容器将在每次请求DAO时(包括自动装配时)创建一个新的DAO实例。 这将允许服务根据需要将具有不同参数的多个DAO用于不同的实体。

这个作用域如此重要的原因是由于Spring初始化容器中bean的方式。 将通用DAO保留为没有作用域将意味着使用默认的singleton作用域 ,这将导致DAO的单个实例位于容器中。 对于任何一种更复杂的情况,这显然都是主要的限制。

IGenericDao只是所有DAO方法的接口,因此我们可以将Spring的实现注入(或任何需要的)中:

public interface IGenericDao<T extends Serializable> {T findOne(final long id);List<T> findAll();void create(final T entity);T update(final T entity);void delete(final T entity);void deleteById(final long entityId);
}

2.3。 JPA DAO摘要

public abstract class AbstractJpaDao< T extends Serializable > {private Class< T > clazz;@PersistenceContextEntityManager entityManager;public void setClazz( Class< T > clazzToSet ){this.clazz = clazzToSet;}public T findOne( Long id ){return entityManager.find( clazz, id );}public List< T > findAll(){return entityManager.createQuery( "from " + clazz.getName() ).getResultList();}public void save( T entity ){entityManager.persist( entity );}public void update( T entity ){entityManager.merge( entity );}public void delete( T entity ){entityManager.remove( entity );}public void deleteById( Long entityId ){T entity = getById( entityId );delete( entity );}
}

与Hibernate DAO实现类似,此处直接使用Java Persistence API,再次不依赖于现已弃用的 Spring JpaTemplate

2.4。 通用JPA DAO

与Hibernate实现类似,JPA数据访问对象也很简单:

@Repository
@Scope( BeanDefinition.SCOPE_PROTOTYPE )
public class GenericJpaDao< T extends Serializable >extends AbstractJpaDao< T > implements IGenericDao< T >{//
}

3.注入此DAO

现在,Spring将注入一个DAO 。 此外, 需要指定:

@Service
class FooService implements IFooService{IGenericDao< Foo > dao;@Autowiredpublic void setDao( IGenericDao< Foo > daoToSet ){dao = daoToSet;dao.setClazz( Foo.class );}// ...}

Spring 使用setter注入自动装配新的DAO实例,以便可以使用Class对象自定义实现。 在此之后,DAO已完全参数化,可供服务使用。

当然,还有其他方法可以为DAO指定类-通过反射,甚至以XML。 我偏向于这种简单的解决方案,因为与使用反射相比,其可读性和透明度更高。

4。结论

本文通过提供通用DAO的单个可重用实现,讨论了数据访问层简化 。 在基于Hibernate和JPA的环境中都介绍了此实现。 结果是简化了的持久层,没有不必要的混乱。

有关使用基于Java的配置和项目的基本Maven pom设置Spring上下文的分步介绍,请参阅本文 。

参考:在baeldung博客上,使用JCG合作伙伴 Eugen Paraschiv的Spring和Java Generics简化了DAO 。

翻译自: https://www.javacodegeeks.com/2011/12/simplifying-data-access-layer-with.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/374136.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

强肝保肝养肝4大食物

“强肝的食物,保肝的食物有哪些,养肝的食物有哪些”如果您对这些食物不了解不明白。那就看看专家为您推荐的四款强肝保肝养肝的食物。荔枝&#xff08;供图/华盖&#xff09;一、是荔枝&#xff0c;荔枝可以保肝&#xff0c;对肝有好处根据《本草纲目》记载荔枝有强肝健胰的效果…

如何查看注解实现_该怎么运用注解呢?Java团队元老有话说

来源 | 异步 15讲能学好诞生24年的JAVA吗&#xff1f;你当然会感到怀疑&#xff0c;众所周知&#xff0c;在技术向的IT论坛上&#xff0c;“如何在十天之内快速掌握好Java&#xff1f;”这类问题&#xff0c;往往会招来嘲笑。来源于知乎但在当下&#xff0c;5分钟能看完一部电影…

NXP S32K144开发(一)环境搭建和新建工程

1、首先需要安装S32 Design Studio for ARM&#xff0c;在NXP官网可以搜索到&#xff0c;这玩意也是基于eclipse的 安装好后就可以打开了。 2、新建工程 过程可以参考NXP官网&#xff1a; https://www.nxp.com/document/guide/get-started-with-the-s32k144evb:NGS-S32K144E…

首先记录异常的根本原因

Logback日志库的0.9.30版本带来了一个很棒的新功能&#xff1a;从根&#xff08;最内部&#xff09;异常而不是最外部异常开始记录堆栈跟踪。 当然&#xff0c;我的兴奋与我贡献了此功能无关。 用塞西尔德米勒&#xff08;Cecil B. de Mille&#xff09; 的话来解释&#xff1a…

成功醒言

成功醒言 C01 只有敢犯错误的人才能成事&#xff1b; 只有不犯同样错误的人才能成大事。 C02 固执≠执著&#xff1b; 幻想≠希望。 固执是无目标的执著&#xff1b; 执著是有目标的固执。 幻想是无法兑现的希望&#xff1b; 希望是有望实现的幻想。 固执地执著幻想&#xf…

Android 中的 Service 全面总结

1、Service的种类 按运行地点分类&#xff1a; 类别区别 优点缺点 应用本地服务&#xff08;Local&#xff09;该服务依附在主进程上&#xff0c; 服务依附在主进程上而不是独立的进程&#xff0c;这样在一定程度上节约了资源&#xff0c;另外Local服务因为是在同一进程因此不…

python基础学习1-三元表达式和lambda表达式

#!/usr/bin/env python # -*- coding:utf-8 -*- 三元运算 if else 的简写name "alex" if 11 else "SB" #如果条件成立 赋alex 否则 赋SB print(name)#--------------lambda表达式 f2 lambda a1,a2:a1a2100 #等价 下边函数定义 def f1(a1,a2): return …

怎么让存储过程通用化_怎么做分布式存储的面试?

cholerae 大神已经做了详细回答&#xff0c;http://zenlife.tk/interview-for-distributed-storage.md写于几年前&#xff0c;内容有点稚嫩&#xff0c;WAL辨识度很高, 其他问题一般.CAP不会再问了&#xff0c;专业的存储文献中很少(几乎不)提及CAP或PACELC, 这个词用于市场和销…

Java EE中的配置管理

我尝试配置管理在云计算中具有很多相关性 争论 较早。 实际上&#xff0c;我大胆地宣称配置管理是任何认真尝试从软件中节省几美元的基石。 那么什么是配置管理及其主要目标&#xff1f; 在不使事情变得过于复杂的情况下&#xff0c;我认为接下来的两个目标与事实相差不远。 以…

十年总结,一个JAVA人的十年人生路

十年总结-开篇&#xff1a;歇一歇&#xff0c;才能走的更远经常见坛子里有人问&#xff0c;学习java该如何入手&#xff0c;或者是该学java还是学XX语言。我一直觉得&#xff0c;编程跟语言关系不大&#xff0c;重点是要有解决问题的思路。学习一门语言&#xff0c;其实只是寻求…

(四)Qt实现自定义模型基于QAbstractTableModel (一般)

Qt实现自定义模型基于QAbstractTableModel 两个例子 例子1代码 Main.cpp #include <QtGui>#include "currencymodel.h"int main(int argc, char *argv[]) {QApplication app(argc, argv);//数据源QMap<QString, double> currencyMap;currencyMap.insert(…

pt-query-digest使用介绍【转】

本文来自&#xff1a;http://isadba.com/?p651 一、pt-query-digest参数介绍. pt-query-digest --useranemometer --passwordanemometerpass --review h192.168.11.28,Dslow_query_log,tglobal_query_review \--history h192.168.11.28,Dslow_query_log,tglobal_query_re…

python代码模板_python 代码模板

python中的Module是比较重要的概念。常见的情况是&#xff0c;事先写好一个.py文 件&#xff0c;在另一个文件中需要import时&#xff0c;将事先写好的.py文件拷贝 到当前目录&#xff0c;或者是在sys.path中增加事先写好的.py文件所在的目录&#xff0c;然后import。这样的做法…

Java并发教程–重入锁

Java的synced关键字是一个很棒的工具–它使我们能够以一种简单可靠的方式来同步对关键部分的访问&#xff0c;而且也不难理解。 但是有时我们需要对同步进行更多控制。 我们要么需要分别控制访问类型&#xff08;读取和写入&#xff09;&#xff0c;要么使用起来很麻烦&#xf…

找出互联网类似以下图的实例

转载于:https://www.cnblogs.com/sghcjy/p/4978851.html

python比较运算符重载_python运算符重载

1、打印操作会首先尝试__str__和str内置函数&#xff0c;他通常返回一个用户友好显示。__repr__用于所有其他环境&#xff0c;用于交互式模式下提示回应以及repr函数&#xff0c;如果没有使用__str__&#xff0c;则会使用print和str。它通常返回一个编码字符串&#xff0c;可以…

使用Spring MVC开发Restful Web服务

REST简介 摘自Wikipedia&#xff1a; REST风格的体系结构由客户端和服务器组成。 客户端向服务器发起请求&#xff1b; 服务器处理请求并返回适当的响应。 请求和响应围绕资源表示的传递而构建。 资源本质上可以是可以解决的任何连贯且有意义的概念。 正如您所阅读的&#xff0…

深入Java核心 Java内存分配原理精讲

深入Java核心 Java内存分配原理精讲 Java内存分配与管理是Java的核心技术之一&#xff0c;之前我们曾介绍过Java的内存管理与内存泄露以及Java垃圾回收方面的知识&#xff0c;今天我们再次深入Java核心&#xff0c;详细介绍一下Java在内存分配方面的知识。一般Java在内存分配时…

iOS正则表达式(亲测,持续更新)

先来说说判断方法,书写不简介但是好理解: -(BOOL)isRealNmaeString:(NSString *)str{NSString *pattern "填写正则表达式";NSPredicate *pred [NSPredicate predicateWithFormat:"SELF MATCHES %", pattern];BOOL isMatch [pred evaluateWithObject:str…

python新建一个文件夹需要重新安装模块吗_解决pycharm每次新建项目都要重新安装一些第三方库的问题...

目前有三个解决办法&#xff0c;也是亲测有用的&#xff1a;第一个方法&#xff1a;因为之前有通过pycharm的project interpreter里的号添加过一些库&#xff0c;但添加的库只是指定的项目用的&#xff0c;如果想要用&#xff0c;就必须用之前的项目的python解释器&#xff0c;…