使用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上下文的分步介绍,请参阅本文 。
翻译自: https://www.javacodegeeks.com/2011/12/simplifying-data-access-layer-with.html
使用Spring和Java泛型简化数据访问层相关推荐
- Generic Data Access Layer泛型的数据访问层
http://www.codeproject.com/Articles/630277/Generic-Data-Access-Layer-GDA-Part-I http://www.codeproje ...
- 分层:数据访问层、业务逻辑层、视图层
分层:开发模式 数据访问层 业务逻辑层:调用数据访问层 视图层:调用业务逻辑层 数据库表 1.创建项目 2.创建包: com.zking.util com.zking. ...
- Spring Data:企业级Java的现代数据访问技术(影印版)
<Spring Data:企业级Java的现代数据访问技术(影印版)> 基本信息 原书名:Spring Data:Modern Data Access for Enterprise Jav ...
- Spring Boot - 构建数据访问层
文章目录 基础规范: JDBC 关系型数据库访问规范 JDBC 规范中的核心编程对象 DriverManager DataSource Connection Statement/PreparedSta ...
- Spring.Net+NHibenate+Asp.Net mvc +ExtJs 系列 3 ----数据访问层
在上一篇中,我们已经搭建起了整个解决方案的项目,并且建好了数据库,完成了实体类和Nhibernate映射文件.在本文中,将定义数据访问接口,并利用Nhibernate实现接口,利用Spring.net ...
- java数据访问层实例_java实际项目先写哪一层?java三层架构是什么?
在写java实际项目的时候,我们都是要有思维逻辑的,哪一层先写哪一层后写,这些都要考虑清楚,那么接下来,我们就来给大家讲解一下这方面的内容. 这没有标准,一般是controller-service-d ...
- java中表示层 控制层 业务逻辑层 数据访问层
控制层(controller):的职能是负责读取视图表现层的数据,控制用户的输入,并调用业务层的方法: 业务层(service):需要根据系统的实际业务需求进行逻辑代码的编写,有些业务逻辑需要通过与数 ...
- Java job interview:项目开发小组成员网站数据访问层设计
在前面简单描述了下服务层,SOA面向服务架构,架构设计-业务逻辑层,以及一些面面向设计原则理解和软件架构设计箴言.这篇博客我们将继续进入我们的下一层:数据访问层.无论你用的是什么开发模式或者是业务模式 ...
- java三层架构(表示层,业务逻辑层,数据访问层,与两层的区别,三层架构的优缺点)
目录 1 什么是三层 2 为什么使用三层 3 与两层的区别 1 什么是三层 UI(表现层): 主要是指与用户交互的界面.用于接收用户输入的数据和显示处理后用户需要的数据. BLL:(业务逻辑层): U ...
最新文章
- 写在创业的路上:如何从无到有的打造一个产品
- Vue中使用vue-video-player和videojs-flash插件实现播放rtmp视频文件流
- doorway path issue of my task in HCP
- UART 异步串行通信发送模块设计与实现
- 为什么配置了vsftpd.conf文件,用户还是可以访问上级目录?
- MySQL单机多实例部署详解之------多实例分别定义不同的配置文件
- Zend Studio使用教程:序列号注册
- C语言形参和实参以及C#中的ref
- vs 中使用32 位mysql_【转载】VS中MFC连接MySQL由于系统不同位(32/64)引起的错误:无法解析的外部符号 _mysql_init@4、_mysql_query...
- ArcPad 10 使用与同步 ArcGIS Server 的数据全攻略(二)
- 小学-综合素质【5】
- pyautogui在网页内写入excel文件内容
- java实现26个大写字母的遍历
- css如何使文字抖动,CSS美化:实现抖音彩色文字抖动效果
- k8s学习-Secret(创建、使用、更新、删除等)
- 1000行代码徒手写正则表达式引擎【1】--JAVA中正则表达式的使用
- Java开发 - 树(二叉树,二叉排序树,红黑树)
- ‘When we dream, we have the perfect chemical canvas for intense visions’ “入梦时,我们就拥有了能够呈现强烈幻象的完美化学画布”
- QPS、TPS、RT、并发用户数、吞吐量
- STM32 USB音频麦克风实现
热门文章
- SQL编程---存储过程和存储函数
- 小程序真机测试错误代码_测试不充分:知道您的代码是否真的可以投入生产的5种方法...
- netty java_Netty Java快速指南
- 多云和混合云_多云互操作性!=云服务聚合
- kafka grpc_模型服务:流处理与使用Java,gRPC,Apache Kafka,TensorFlow的RPC / REST
- jdbc事务 jta事务_将非事务性资源绑定到JTA事务中的几种模式
- jooq_jOOQ与Hibernate:何时选择哪个
- 如何在Spring Boot应用程序中使用配置文件
- JDK 12 Early Access Build 12中的原始字符串文字支持
- Elasticsearch –使用模式替换过滤器和自定义分析器忽略查询中的特殊字符