在这里,我们将给大家分享关于SpringJava中许多DAO的策略的知识,让您更了解java里spring的本质,同时也会涉及到如何更有效地Java10.Spring--AOP编程、Java:Spri
在这里,我们将给大家分享关于Spring Java中许多DAO的策略的知识,让您更了解java里spring的本质,同时也会涉及到如何更有效地Java 10.Spring--AOP 编程、Java : Spring基础 AOP、java day59【 AOP 的相关概念[理解] 、 Spring 中的 AOP[掌握] 、 Spring 整合 Junit[掌握] 】、JAVA Spring Data JPA中的动态查询代码详解的内容。
本文目录一览:- Spring Java中许多DAO的策略(java里spring)
- Java 10.Spring--AOP 编程
- Java : Spring基础 AOP
- java day59【 AOP 的相关概念[理解] 、 Spring 中的 AOP[掌握] 、 Spring 整合 Junit[掌握] 】
- JAVA Spring Data JPA中的动态查询代码详解
Spring Java中许多DAO的策略(java里spring)
我们在现有项目中有许多DAO(目前没有接口,但可以改变).我们没有为每个DAO类连接一个Spring管理的bean并将它们注入服务层,而是有一个类似于这样的DAO“工厂”:
public class DAOFactory {
private static DAOFactory daoFac;
static{
daoFac = new DAOFactory();
}
private DAOFactory(){}
public static DAOFactory getInstance(){
return daoFac;
}
public MyDAO1 getMyDAO1(){
return new MyDAO1();
}
public MyDAO2 getMyDAO2(){
return new MyDAO2();
}
...
(注意MyDAO1和MyDAO2是具体的类)
这允许我们在服务层内轻松添加/调用DAO方法,而不必1.)将DAO接口作为属性添加到服务类2.)通过配置将DAO实现连接到服务方法. (我们有时在一个服务类中使用多个DAO).
DAOFactory.getInstance().getMyDAO1().doSomething();
到目前为止,这个策略对我们有用(我们不太需要切换实现),但我想知道如果我们能够开始新的更好的方法吗?我考虑将DAO自动装配为bean,但我仍然需要在每个服务类中创建属性来表示正在使用的DAO.在一个大型项目中,我仍然犹豫是否开始自动布线bean – 我们需要为所有开发人员提供可见性.
感觉就像我在一个实体之间紧密耦合,但是更少的代码/配置开销和b.)松散地耦合到接口,但需要大量的代码/配置开销.
有没有更好的方法让我失踪?介于两者之间?意见表示欢迎.
只需使用@Component注释每个DAO类
并用.替换MyDao mydao = factory.getmyDao()
@Autowired
MyDao myDao;
我没有看到它的编码/配置开销.
Java 10.Spring--AOP 编程
1. 创建 web 项目
2. 引入 jar 包
在原有的 jar 包加上 AOP 的 jar 包
3. 日志
4. 准备目标对象
先创建接口
在创建实现类
package com.Spring.aop.service;
public class UserServceImpl implements UserService {
@Override
public void save() {
System.out.println("保存用户");
// TODO Auto-generated method stub
}
@Override
public void delete() {
System.out.println("删除用户");
// TODO Auto-generated method stub
}
@Override
public void update() {
System.out.println("更新用户");
// TODO Auto-generated method stub
}
@Override
public void select() {
System.out.println("查询用户");
// TODO Auto-generated method stub
}
}
5. 编写通知
前置通知:在目标方法之前调用
后置通知(如果出现异常就不调用):在目标方法之后调用
后置通知(无论是否出现异常都会调用):在目标方法之后调用
环绕通知:在目标方法之后调用
异常通知:出现异常调用
package com.Spring.aop.advice;
import org.aspectj.lang.ProceedingJoinPoint;
public class TransactionAdvice {
// 前置通知:在目标方法之前调用
//
// 后置通知(如果出现异常就不调用):在目标方法之后调用
//
// 后置通知(无论是否出现异常都会调用):在目标方法之后调用
//
// 环绕通知:在目标方法之后调用
//
// 异常通知:出现异常调用
public void before() {
System.out.println("前置通知被执行");
}
public void afterReturning() {
System.out.println("后置通知(如果出现异常就不调用)");
}
public void after() {
System.out.println("后置通知(无论是否出现异常都会调用)");
}
public void afterException() {
System.out.println("异常通知被执行");
}
public Object around(ProceedingJoinPoint point) throws Throwable {
System.out.println();
Object proceed = point.proceed();
return proceed;
}
}
6. 配置织入,将通知织入到目标对象
加入 AOP 名称空间
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd"
>
<!-- 目标对象 -->
<bean name="userServce" class= "com.Spring.aop.service.UserServceImpl"></bean>
<!-- 通知对象 -->
<bean name="transactionAdvice" class= "com.Spring.aop.advice.TransactionAdvice" ></bean>
<!-- 将通知对象织入到目标对象 -->
<aop:config>
<!-- 选择切入点 -->
<aop:pointcut expression="execution(. com.Spring.aop.service..*ServceImpl.*(..))" id="pointcut"/>
<aop:aspect ref="transactionAdvice">
<aop:before method="before" pointcut-ref="pointcut"/>
<aop:after-returning method="afterReturning"/>
<aop:after method="after" pointcut-ref="pointcut"/>
<aop:around method="around" pointcut-ref="pointcut"/>
<aop:after-throwing method="afterException" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
</beans>
7. 测试
package com.Spring.aop.service;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AopTest {
@Resource(name="userService")
private UserService userService;
@Test
public void testSave() {
userService.save("yu jack");
}
@Test
public void testUpdate() {
userService.update();
}
}
Java : Spring基础 AOP
简单的JDK动态代理例子(JDK动态代理是用了接口实现的方式)(ICar是接口, GoogleCar是被代理对象, MyCC是处理方法的类):
public class TestCar {
public static void main(String[] args) {
ICar car = (ICar) Proxy.newProxyInstance(TestCar.class.getClassLoader(), GoogleCar.class.getInterfaces(), new MyCC());
car.start();
car.run();
}
}
class MyCC implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("start")) {
System.out.println("do something...");
}
method.invoke(new GoogleCar(), args);
return null;
}
}
===============================================================================
简单的cglib动态代理例子(cglib是用了继承的方式实现动态代理):
public class CglibProxy implements MethodInterceptor {
private CustomerDao customerDao;
public CglibProxy(CustomerDao customerDao) {
this.customerDao = customerDao;
}
public CustomerDao createProxy() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(customerDao.getClass());// 设置父类
enhancer.setCallback(this);//设置回调,也就是处理的类,这里因为自身实现了这个接口,重写intercept方法
return (CustomerDao) enhancer.create();//创建代理对象
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("增强方法...");
return methodProxy.invokeSuper(o, objects);
}
}
===============================================================================
springAOP是基于AspectJ(静态代理)和Cglib(动态代理)的
专业术语:
Joinpoint(连接点): 指的是可以被拦截到的点,比如一个类里面有四个方法,这四个方法都可以被拦截并增加功能,这四个方法都叫做连接点.
Pointcut(切入点): 真正被拦截到的点,如果四个方法只有一个被拦截并增强了, 这个方法就叫切入点.
Advice(通知/增强): 对一个方法进行增强或者权限校验的方法被称为 Advice. 方法层面的增强(在方法前后增强)
Introduction(引介): 类层面的增强, 比如动态加个属性,加个方法
Target: 被增强的对象(被代理的对象).
Weaving(织入): 将Advice应用到Target的过程,简单来说就是增强或者校验的过程.
Proxy(代理): 代理对象,生成的代理对象.
Aspect(切面): 多个通知和多个切入点的组合,称为一个切面.
spring通知类型:
前置通知: 在目标方法之前进行操作
后置通知: 在目标方法之后进行操作
环绕通知: 在执行之前和之后进行操作
异常抛出通知: 出现异常的时候进行的操作
最终通知: 无论代码是否有异常,总会进行操作,相当于finally代码块
引介通知:.....暂时不了解
===============================================================================
XML方式(其中MyAspectXML是权限校验的类,里面的checkPri是权限校验方法,需要在ProductDaoImpl.save方法前执行):
<bean id="productDao" class="com.smile.myweb.ProductDaoImpl"/>
<bean id="myAspectXML" class="com.smile.myweb.MyAspectXML"/>
<aop:config>
<aop:pointcut id="pointcut1" expression="execution(* com.smile.myweb.ProductDaoImpl.save(..))"/>
<aop:aspect ref="myAspectXML">
<aop:before method="checkPri" pointcut-ref="pointcut1"/>
</aop:aspect>
</aop:config>
===============================================================================
注解方式 需要开启配置 <aop:aspectj-autoproxy/>
然后把需要增强的类和代理类都加入IOC 在代理类上面添加@Aspect注解,在增强上面使用@Before或@AfterReturing等注解,如:
@Aspect
public class MyAspectAnno {
@Before(value = "execution(* com.smile.myweb.OrderDao.save(..))")
public void before() {
System.out.println("前置通知~~~");
}
}
@Before 前置通知 例子略
@AfterReturing 后置通知 后置通知可以接受返回值,使用注解里面的 returning 参数:
---------------------------------------------------------------------------------------
@AfterReturning(value = "execution(* com.smile.myweb.OrderDao.save(..))", returning = "result")
public void after(Object result) {
System.out.println("后置通知~~~");
System.out.println(result);
}
@Around 环绕通知
------------------------------------------------------------------------------------------
@Around(value = "execution(* com.smile.myweb.OrderDao.save(..))")
public void after(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕前~");
Object object = joinPoint.proceed();// 执行的方法 object为返回值
System.out.println("环绕后~");
System.out.println(object);
}
@AfterThrowing 异常抛出通知 有异常抛出的时候才会执行:
-----------------------------------------------------------------------------------------
@AfterThrowing(value = "execution(* com.smile.myweb.OrderDao.save(..))", throwing = "e")
public void after(Throwable e){
System.out.println("异常" + e.getMessage());
}
@After 最终通知 例子略
========================================================================
切入点注解: @Pointcut 如果有很多个通知作用于同一个方法,那么只需要声明一个空方法,加上这个注解,然后在别的通知的注解的value值写上 类名.方法名() 就可以了 如:
-------------------------------------------------------------------------------------------
@After(value = "MyAspectAnno.pointcut1()")
public void after(){
System.out.println("最终通知");
}
@Pointcut(value = "execution(* com.smile.myweb.OrderDao.save(..))")
private void pointcut1() {}
try
{
try
{
//@Before
method.invoke(..);
}
finally
{
//@After
}
//@AfterReturning
}
catch
(){
//@AfterThrowing
}
java day59【 AOP 的相关概念[理解] 、 Spring 中的 AOP[掌握] 、 Spring 整合 Junit[掌握] 】
第1章 AOP 的相关概念[理解]
1.1AOP 概述
1.1.1 什么是 AOP
1.1.2 AOP 的作用及优势
1.1.3 AOP 的实现方式
1.2AOP 的具体应用
1.2.1 案例中问题
1.2.2 问题的解决
1.2.3 新的问题
1.2.4 动态代理回顾
1.2.4.1 动态代理的特点
1.2.4.2 动态代理常用的有两种方式
1.2.4.3 使用 JDK 官方的 Proxy 类创建代理对象
1.2.4.4 使用 CGLib 的 Enhancer 类创建代理对象
1.2.5 解决案例中的问题
第2章 Spring 中的 AOP[掌握]
2.1Spring 中 AOP 的细节
2.1.1 说明
2.2.1.5 第五步:抽取公共代码制作成通知
2.3基于注解的 AOP 配置
2.3.1 环境搭建
JAVA Spring Data JPA中的动态查询代码详解
spring data jpa大大的简化了我们持久层的开发,但是实际应用中,我们还是需要动态查询的。
比如,前端有多个条件,这些条件很多都是可选的,那么后端的SQL,就应该是可以定制的,在使用hibernate的时候,可以通过判断条件来拼接SQL(HQL),当然,Spring Data JPA在简化我们开发的同时,也是提供了支持的。
通过实现Criteria二实现的动态查询,需要我们的Repo接口继承JpaSpecificationExecutor接口,这是个泛型接口。
然后查询的时候,传入动态查询参数,分页参数等即可。
使用起来很简单,不过为了知其所以然,先介绍一下Criteria API。
立即学习“Java免费学习笔记(深入)”;
Criteria API
如果编译器能够对查询执行语法正确性检查,那么对于 Java 对象而言该查询就是类型安全的。Java™Persistence API (JPA) 的 2.0 版本引入了 Criteria API,这个 API 首次将类型安全查询引入到 Java 应用程序中,并为在运行时动态地构造查询提供一种机制。本文介绍如何使用 Criteria API 和与之密切相关的 Metamodel API 编写动态的类型安全查询。
在使用Spring Data JPA的时候,只要我们的Repo层继承JpaSpecificationExecutor接口就可以使用Specification进行动态查询了,我们先看下JpaSpecificationExecutor接口:
public interface JpaSpecificationExecutor<T> { T findOne(Specification<T> spec); List<T> findAll(Specification<T> spec); Page<T> findAll(Specification<T> spec, Pageable pageable); List<T> findAll(Specification<T> spec, Sort sort); long count(Specification<T> spec); }
可以看到提供了5个方法,方法的参数和返回值已经很明显的表达了其意图。其中的参数,Pageable和Sort应该是比较简单的,分别是分页参数和排序参数,而重点就是Specification参数,先看下这个接口的定义:
public interface Specification<T> { Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb); }
其中就一个方法,返回的是动态查询的数据结构。
javax.persistence.criteria.Predicate toPredicate(javax.persistence.criteria.Root<T> root, javax.persistence.criteria.CriteriaQuery<?> query, javax.persistence.criteria.CriteriaBuilder cb);
这里使用的都是Java EE中的规范,具体实现本人采用的是Hibernate,当然也可以选择其他实现了JPA规范的数据持久层框架。
这里需要再次回过头看看Criteria API中的一些东西:
Criteria 查询是以元模型的概念为基础的,元模型是为具体持久化单元的受管实体定义的,这些实体可以是实体类,嵌入类或者映射的父类。
CriteriaQuery接口:代表一个specific的顶层查询对象,它包含着查询的各个部分,比如:select 、from、where、group by、order by等注意:CriteriaQuery对象只对实体类型或嵌入式类型的Criteria查询起作用
Root接口:代表Criteria查询的根对象,Criteria查询的查询根定义了实体类型,能为将来导航获得想要的结果,它与SQL查询中的FROM子句类似
1:Root实例是类型化的,且定义了查询的FROM子句中能够出现的类型。
2:查询根实例能通过传入一个实体类型给 AbstractQuery.from方法获得。
3:Criteria查询,可以有多个查询根。
4:AbstractQuery是CriteriaQuery 接口的父类,它提供得到查询根的方法。CriteriaBuilder接口:用来构建CritiaQuery的构建器对象Predicate:一个简单或复杂的谓词类型,其实就相当于条件或者是条件组合
其中支持的方法非常之强大,下面给出一个示例,大家可以参考一下,同样的,可以根据示例,自己可以写出更为复杂的查询:
Repo接口:
public interface DevHREmpConstrastDao extends JpaRepository<DevHREmpConstrast, Long>,JpaSpecificationExecutor<DevHREmpConstrast>
查询实例1:
/** * 条件查询时动态组装条件 */ private Specification<DevHREmpConstrast> where( final String corg,final String name,final String type,final String date,final String checker){ return new Specification<DevHREmpConstrast>() { @Override public Predicate toPredicate(Root<DevHREmpConstrast> root, CriteriaQuery<?> query, CriteriaBuilder cb) { List<Predicate> predicates = new ArrayList<Predicate>(); //机构 if(corg!=null&&!corg.equals("")){ List<String> orgIds = organizationDao.findByName("%"+corg+"%"); if(orgIds.size()>0&&orgIds.size()<1000) predicates.add(root.<String>get("confirmOrgNo").in(orgIds));//confirmOrgNo } //名字 if(name!=null&&!name.equals("")){ List<String> userIds = userDao.findByName(name); if(userIds.size()>0&&userIds.size()<1000)//如果太多就不管了这个条件了 predicates.add(root.<String>get("hrUserName").in(userIds)); } //类型 if(type!=null&&!type.equals("")) predicates.add(cb.equal(root.<String>get("hrUpdateType"),type)); //日期 if(date!=null&&!date.equals("")){ //处理时间 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); Date startDate; Date endDate; try { startDate = format.parse(date); } catch (ParseException e) { startDate = new Date(946656000000L);//2000 01 01 } endDate = startDate; Calendar calendar = Calendar.getInstance() ; calendar.setTime(endDate); calendar.add(Calendar.DATE, 1); endDate = calendar.getTime(); calendar = null; predicates.add(cb.between(root.<Date>get("insDate"),startDate,endDate)); } //审核人 if(checker!=null&&!checker.equals("")){ List<String> userIds = userDao.findByName(checker); if(userIds.size()>0&&userIds.size()<1000)//如果太多就不管了这个条件了 predicates.add(root.<String>get("confirmUserId").in(userIds)); } return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction(); } }; }
查询实例2:
/** * 条件查询时动态组装条件 */ private Specification<DevHREmpConstrast> where( final String corg,final String name,final String type,final String date,final String checker){ return new Specification<DevHREmpConstrast>() { @Override public Predicate toPredicate(Root<DevHREmpConstrast> root, CriteriaQuery<?> query, CriteriaBuilder cb) { List<Predicate> predicates = new ArrayList<Predicate>(); //机构 if(corg!=null&&!corg.equals("")){ List<String> orgIds = organizationDao.findByName("%"+corg+"%"); if(orgIds.size()>0&&orgIds.size()<1000) predicates.add(root.<String>get("confirmOrgNo").in(orgIds));//confirmOrgNo } //名字 if(name!=null&&!name.equals("")){ List<String> userIds = userDao.findByName(name); if(userIds.size()>0&&userIds.size()<1000)//如果太多就不管了这个条件了 predicates.add(root.<String>get("hrUserName").in(userIds)); } //类型 if(type!=null&&!type.equals("")) predicates.add(cb.equal(root.<String>get("hrUpdateType"),type)); //日期 if(date!=null&&!date.equals("")){ //处理时间 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); Date startDate; Date endDate; try { startDate = format.parse(date); } catch (ParseException e) { startDate = new Date(946656000000L);//2000 01 01 } endDate = startDate; Calendar calendar = Calendar.getInstance() ; calendar.setTime(endDate); calendar.add(Calendar.DATE, 1); endDate = calendar.getTime(); calendar = null; predicates.add(cb.between(root.<Date>get("insDate"),startDate,endDate)); } //审核人 if(checker!=null&&!checker.equals("")){ List<String> userIds = userDao.findByName(checker); if(userIds.size()>0&&userIds.size()<1000)//如果太多就不管了这个条件了 predicates.add(root.<String>get("confirmUserId").in(userIds)); } return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction(); } }; }
然后调用dao层方法传入where()方法返回的参数即可。
以上就是JAVA Spring Data JPA中的动态查询代码详解的详细内容,更多请关注php中文网其它相关文章!
今天关于Spring Java中许多DAO的策略和java里spring的讲解已经结束,谢谢您的阅读,如果想了解更多关于Java 10.Spring--AOP 编程、Java : Spring基础 AOP、java day59【 AOP 的相关概念[理解] 、 Spring 中的 AOP[掌握] 、 Spring 整合 Junit[掌握] 】、JAVA Spring Data JPA中的动态查询代码详解的相关知识,请在本站搜索。
本文标签: