SSSHJ---全注解开发
SpringMVC、Spring、SpringData、HiberanteJPA、MySQL
之前的文章当中提及过HiberanteJPA它完成的其实就是利用注解的方式将类与表,行和对象,字段与属性关联起来的一种实现,在这里我们将其与SpringData相结合共同完成持久层的开发,即利用了HiberanteJPA的注解关联到数据库,又利用了SpringData的所提供的方法来操作数据库,当然你也可以使用一些自定义的方法后面会提及到.
那么什么是SpringData?
SpringData相关概念:
SpringData是Spring基于ORM框架、JPA规范封装的一套JPA应用框架,它提供了包括增删改查在内的常用功能,且易于扩展,可使开发者用极简的代码实现对数据库的访问和操作,它的可扩展性就体现在在,它除了可以使用本身框架提供的方法之外,还可以自定义方法来根据需求来补充,这也是当下它流行的原因吧。
之前又一篇专门讲解JPA的文章,想了解的可以去细读,这里再提及一下:
那么什么是JPA呢?
JPA其实是ELB当中的实体Bean分离出来的规范,在EJB3.0推出以后,实体Bean被单独分了出来,形成了新的规范JPA
JPA全称Java Persistence API,是sun提出的一个对象持久化规范,各JavaEE应用服务器自主选择具体实现。JPA仅仅只是一个规范,而不是产品;使用JPA本身是不能做到持久化的。所以,JPA只是一系列定义好的持久化操作的接口,在系统中使用时,需要真正的实现者,之前的博文使用的实现就是hibernateJPA.
JPA的设计者是Hibernate框架的作者,因此Hibernate EntityManager作为Jboss服务器中JPA的默认实现;Oracle的Weblogic使用EclipseLink(以前叫TopLink)作为默认的JPA实现;IBM的Websphere和Sun的Glassfish默认使用OpenJPA(Apache的一个开源项目)作为其默认的JPA实现。
JPA的底层实现是一些流行的开源ORM(对象关系映射)框架,因此JPA其实也就是java实体对象和关系型数据库建立起映射关系,通过面向对象编程的思想操作关系型数据库的规范。
而对于Spring Data JPA 来说: 致力于减少数据访问层 (DAO) 的开发量. 开发者唯一要做的,就只是声明持久层的接口,其他都交给 Spring Data JPA 来帮你完成!
什么是ORM呢?
ORM,即Object-Relational Mapping(对象关系映射),它的作用是在关系型数据库和业务实体对象之间作一个映射,这样,我们在具体的操作业务对象的时候,就不需要再去和复杂的SQL语句打交道,只需简单的操作对象的属性和方法。
只要提供了持久化类与表的映射关系,ORM框架在运行时就能参照映射文件的信息,把对象持久化到数据库中。当前ORM框架主要有三种:Hibernate,iBATIS,EclipseLink。
下面是SpringData提供的几个编程接口:
Repository:最顶层接口,是一个空接口,目的是为了统一所有的Repository的类型,且能让组件扫描的时候自动识别;后面的项目当中会用到,下图就是i这个顶级的接口;
CrudRepository:提供基础的增删改查操作;你自己可以使用注解在此基础之上扩展,下面就是这个接口,继承了顶级接口:
PagingAndSortingRepository:提供分页和排序的操作;根据源码可知,你只需要传入两个参数,就是Page(第几页),size(一页的记录数量),当然在传入的时候是分装陈一个类,这个类就是Pageable;
JpaRepository:增加了批量操作的功能;
JpaSpecificationExecutor :组合查询条件,提供原生SQL查询。
接下来我们就来开发一个,简单的体验一下,其中在框架提供的方法当中我么以分页查询为例,自定义方法我们以模糊查询为例,而自定义事务方法我们以updatename为例:
首先我们做的就是创建项目导入依赖:
这次用到的除了之前SSH当中用到的依赖之外,还应该加入的就是SpringDate,具体如下图所示:
在搭建好了基本的框架之后,我们根据我们数据库当中的表来编写一个实体类,我们用的环视上篇博文中的javauser表,在写好了类之后,我们更具hibernate为JPA提供的实现,给这个实体类加入注解,完成之前提到的类和表的,对象和行,属性和字段的关联,一下就是我们编写的实体类:
在此处只是提供了注解所在的地方,其余的get,set方法大家可以自己去加,相信大家读过之前博文的看到下面的代码不会陌生,这儿在来加单的说一下; @Entity //表示着是一个实体类 ///表示这个实体类关联的是javauser这张表 //以上两部完成的就是我们的第一个关联,表和类的关联 public class Javauser { @Id //表示这是主键 @GeneratedValue(strategy = GenerationType.IDENTITY) //定义了主键的生成方式此处是自增长 @Column(name = "id") //意思是这个属性对应的是表当中的id这个字段 //以上三个注解完成的就是第二个关联,行和对象的关联 private Integer id; @Column(name = "name") //表示这个类的属性对应的是数据库表当中的name字段 private String name; @Column(name = "password") //同样这个表示对于=应表中的字段是pasword private String password;// 以上两部就完成了属性与对象的关联,至此三个关联就完成了 assword, javauser.password); } |
在此处只是提供了注解所在的地方,其余的get,set方法大家可以自己去加,相信大家读过之前博文的看到下面的代码不会陌生,这儿在来加单的说一下; @Entity //表示着是一个实体类 ///表示这个实体类关联的是javauser这张表 //以上两部完成的就是我们的第一个关联,表和类的关联 public class Javauser { @Id //表示这是主键 @GeneratedValue(strategy = GenerationType.IDENTITY) //定义了主键的生成方式此处是自增长 @Column(name = "id") //意思是这个属性对应的是表当中的id这个字段 //以上三个注解完成的就是第二个关联,行和对象的关联 private Integer id; @Column(name = "name") //表示这个类的属性对应的是数据库表当中的name字段 private String name; @Column(name = "password") //同样这个表示对于=应表中的字段是pasword private String password;//以上两部就完成了属性与对象的关联,至此三个关联就完成了 |
|
至于实体类其实是可以自动生成的,之前又一篇博文讲的就是hibernate的逆向工程,在生成实体类以及映射文件的时候我们要是只想要生成实体类,可以只勾选去生成实体类,不去生成映射文件;
以上我们就以及基本上完成可基本的环境搭建以及基础资源实体类的变写,接下来同样的套路,:
1.Dao层的开发
但要注意的就是,这里Dao层的开发和之前的大有不同,由于SpringData的加入,在这个接口当中我们是不需要去声明任何的方法的,当然除了你自己自定义的,当然基本的CRDU是可以完成的,至于自定义我们后面会提到;
在这个地方,我们需要去实现一个接口,就是JpaRepository之前提到过常用的几个接口,增加了批量操作的功能,它继承的接口是:
我们来看一下这个接口的源码:
由上图我们可以知道,实现这个接口需要传入两个参数,一个是类,一个是id应以序列化而且它是继承了PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T>这两个接口,
前者的源码:
我们可以从这里看到这个接口由去继承了CrudRepository<T, ID>而这个接口又是继承等级接口的,所以说环环相扣使得这个类具有了前者功能的时候又自己添加的功能,所以说还是比较丰富的;而且我们可以从这里得到的一个信息就是,这里有一个方法Page<T> findAll(Pageable var1);它需要的就是Pageable这样的一个类,而这个类当中就可以封装我们传入的参数第几页page以及每一页的大小size;
以上就是我们对这个类的解读,下面就是Dao接口的代码:
2.服务层的开发
当然我们也应该首先去写一个dto的类,用于和表现层的交互;
之前的博文都有提及,这儿就不再赘述了;
服务层有它的接口以及实现类,我们用注解的方式,类实现创建对象,以及Dao对象的注入,一下就是代码:
接口的方法:
实现类的注解
实现的方法:
@Override public List<userDto> findByPage(int page, int size) { List<userDto> list=new ArrayList<>(); Pageable pageable=new PageRequest(page,size); //这儿就是对我们传过来的参数进行封装,然后当作参数传入方法 Page<Javauser> all = userDao.findAll(pageable); for (Javauser javauser : all) { userDto userDto1=new userDto(); BeanUtils.copyProperties(javauser,userDto1); list.add(userDto1); } //这个循环的迭代就是将我们遍历出来的集合,,转换我为我们需要的dto return list; |
这样我们的实现层就开发完毕
3.表现层的开发
同样我们使用注解的方式来开发
@Controller public class UserController { @Autowired private Userservie userservie; public ModelAndView Page(HttpServletRequest request){ ModelAndView modelAndView=new ModelAndView(); String start = request.getParameter("start"); String r = request.getParameter("size"); List<userDto> byPage = userservie.findByPage(Integer.parseInt(start) , Integer.parseInt(r)); modelAndView.addObject("PageUser",byPage); modelAndView.setViewName("/UserListByPage.jsp"); return modelAndView; } |
到这里就完成了功能的开发,接下来就是我们的配置,虽说是全注解开发,但配置是不可少的嘛!
4.配置文件
数据源 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/user?characterEncoding=utf-8"></property> <property name="password" value="root2"></property> <property name="user" value="root"></property> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> </bean> 产生实体工厂 <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="jpaProperties">完成扩展属性的配置 <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQL55Dialect</prop> <prop key="format_sql">true</prop> <prop key="show_sql">true</prop> </props> </property> <!-- 注册实体--> <property name="packagesToScan" value="com.ww.pojo"></property> <!-- jpa的适配器,给接口,然后创建其实现来的对象,多态,父类引用子类对象--> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"></bean> </property> </bean> <!-- 因为Dao是没有实类的所以用jpa的扫描来生成动态代理的是实现类,并注入之前创建的工厂对象,关联事务管理类对象--> <jpa:repositories base-package="com.qf.Dao" entity-manager-factory-ref="entityManagerFactory" transaction-manager-ref="transactionManager"></jpa:repositories> <!-- 创建服务层对象--> <context:component-scan base-package="com.qf.service"></context:component-scan> <!-- 创建jpa的事务管理类对象--> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"></bean> <!-- AOP注解事务--> <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven> </beans> |
下面是配置文件的头部约束:
<?xml version="1.0" encoding="UTF-8"?> |
下面是表现层配置:
<!-- 8,创建表现层对象 也是扫描 和服务层的扫描方式是一样的.和服务层的注解组合 --> <context:component-scan base-package="com.qf.controller"></context:component-scan> <!-- 9,配置注解的处理器映射器和适配器 --> <mvc:annotation-driven></mvc:annotation-driven> <!-- 10,视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> </bean>
对于前端控制器的配置和之前的博文一样,这里就不再赘述了;
接下来就编写前端页面进行测试即可;
下图是小编在调试的时候截的图,我们明显的可以看出来的就是i最后一行userDao的代理实现类;用的就是jdk代理。
接下来我们来创建一些自定义方法:
前者是一个查询的方法,所以它是不需要事务的所以,我们只需要@Query来在方法上面定义jsql语句即可,SpringDate会自己去动态的生成它的实现类;
但对于后者来说,因为是属于增删改的操做它是需要事务的,所以我们换还应该在它的上面加上@Modify来声明这是一个更改操做,还需要做的就是,在其相应的服务层上面加上@Transactional来表面这个自定义的方法是需要事务的,所以在集团操作的时候,框架会根据这两个注解组合给我给所在的方法加上事务,否则所做的更更改是不能同步到库找中的,下面就是后者的服务层是现方法:
@Override @Transactional public void updateName(int id, String name) { userDao.updateName(id,name); }
之后大家可以自行编写实现类去测试,代码资源可以去小编的资源上去下载;
好了今天的分享就到这里,后还会有,组合整合,敬请期待!