Spring Data JPA学习一

1、Spring框架对JPA的支持

1、spring使jpa配置更加灵活。JPA规范要求,配置文件必须命名为persistence.xml,并存在于类路径下的META-INF目录中。该文件通常包含了初始化JPA引擎所需的全部信息。Spring提供的LocalContainerEntityManagerFactoryBean提供了非常灵活的配置,persistence.xml中的信息都可以在此以属性注入的反射提供。

2、Spring实现了部分在EJB容器环境下才具有的功能,如@PersistenceContext、@PersistenceUnit的容器注入支持。

3、Spring将EntityManager的创建与销毁、事务管理等代码抽取出来,并由统一管理,开发者不需要关心这些,业务方法中只剩下操作领域对象的代码,事务管理和EntityMangaer创建、销毁的代码都不在需要开发者关心。

2、Spring Data JPA的使用

1、下载需要的包:Spring Data Commons和Spring Data JPA jar

2、让持久层接口Dao继承Repository接口

该接口使用泛型,需要为其提供两个类型:第一个为该接口处理的域对象,第二个为该域对象的主键类型。

Spring Data JPA风格的持久层接口:

public interface UserDao extends Repository<User,Long>{

public User save(User user);

}

不需要UserDao的实现类,框架会为我们完成业务逻辑。

3、在Spring配置文件中启用扫描并自动创建代理的功能

<--需要在<beans>标签中增加jpa命名空间的引用-->

<jpa:repositories base-pack="包名" entity-manager-factory-ref="entityManagerFactory" transaction-manager-ref="transactionManger"/>

3、开发步骤

1、声明持久层的接口,该接口继承Repository,Repository是一个标记型接口,它不包含任何方法,如需要可以继承其子类接口,定义了常用的增删改查以及分页的方法。

2、在接口中声明需要的业务方法。Spring Data将根据给定的策略为其生成实现代码。

3、在Spring配置文件中增加一行声明,让Spring为声明的接口创建代理对象。配置了<jpa:repositories>后,Spring初始化容器时将会扫描base-package指定的包目录及其子目录,为继承Repository或其子接口的接口创建代理对象,并将代理对象注册为Spring Bean,业务层便可以通过Spring自动封装的特性来直接使用该对象。

此外,<jpa:repository>还提供了一些属性和子标签,便于更细粒度的控制。可以再<jpa:repository>内部使用<context:include-filter>、<context:exclude-filter>来过滤掉一些不想被扫描到的接口。

4、接口继承

持久层接口继承Repository并不是唯一选择。Repository接口是Spring Data的一个核心接口,它不提供任何方法,开发者需要在自己定义的接口中声明需要的方法。

与继承Repository等价的一种方式,是在持久层接口上使用@RepositoryDefinition注解,并为其指定domainClass和idClass属性。

public interface UserDao extends Repository<User,Long>{}等价于

@RepositoryDefinition(domainClass=User.class,idClass=Long.class)

public interface UserDao{}

1、如持久层每个接口都需要增删改查方法,可以继承CrudRepository,其副作用是暴露了你不希望暴露个业务层的方法。

2、分页查询和排序,可以继承PagingAndSortingRepository接口,他继承于CrudRepository接口。一般很少直接继承PagingAndSortingRepository,而是在继承Repository或CrudRepository的基础上,在自己的方法参数列表最后增加一个Pageable或Sort类型的参数,用于指定分页或排序信息,会更加灵活。

3、JpaRepository是继承PaingAndSortingRepository的针对JPA技术提供的接口,它在父接口的基础上,提供了其他一些方法,flush(),saveAndFlush(),deleteInBatch()等。

5、查询方式

1、通过解析方法名创建查询

框架在进行方法名解析时,会先把方法名多余的前缀去掉,比如find、findBy、read、readBy、get、getBy,然后对剩下部分进行解析。并且如果方法的最后一个参数是Sort或者Pageable类型,也会提供相关的信息,以便按规则进行排序或者分页查询。

在创建查询时,我们通过在方法名中使用属性名称来表达,比如findByUserAddressZip()。框架在解析该方法时,首先剔除findBy,然后对剩下的属性进行解析,规则如下:

先判断findByUserAddressZip是否是User的一个属性,如果是,则表示根据该属性进行查询;如果没有该属性,继续第二步;

从右往左截取第一个大写字母开头的字符串,然后检查剩下的字符串(findByUserAddress)是否是User的一个属性,如果是,则根据该属性进行查询;如果没有该属性,重复执行该步骤;最后假设userAddress是User的一个属性;

接着处理剩下的部分(Zip),先判断userAddress对应的类型是否有Zip属性,如果有,则表示该方法最终是根据User.userAddress.zip的取值进行查询;否则按步骤2进行。

Spring Data JPA 为此提供了一些表达条件查询的关键字,大致如下:

  • And --- 等价于 SQL 中的 and 关键字,比如 findByUsernameAndPassword(String user, Striang pwd);
  • Or --- 等价于 SQL 中的 or 关键字,比如 findByUsernameOrAddress(String user, String addr);
  • Between --- 等价于 SQL 中的 between 关键字,比如 findBySalaryBetween(int max, int min);
  • LessThan --- 等价于 SQL 中的 "<",比如 findBySalaryLessThan(int max);
  • GreaterThan --- 等价于 SQL 中的">",比如 findBySalaryGreaterThan(int min);
  • IsNull --- 等价于 SQL 中的 "is null",比如 findByUsernameIsNull();
  • IsNotNull --- 等价于 SQL 中的 "is not null",比如 findByUsernameIsNotNull();
  • NotNull --- 与 IsNotNull 等价;
  • Like --- 等价于 SQL 中的 "like",比如 findByUsernameLike(String user);
  • NotLike --- 等价于 SQL 中的 "not like",比如 findByUsernameNotLike(String user);
  • OrderBy --- 等价于 SQL 中的 "order by",比如 findByUsernameOrderBySalaryAsc(String user);
  • Not --- 等价于 SQL 中的 "! =",比如 findByUsernameNot(String user);
  • In --- 等价于 SQL 中的 "in",比如 findByUsernameIn(Collection<String> userList) ,方法的参数可以是 Collection 类型,也可以是数组或者不定长参数;
  • NotIn --- 等价于 SQL 中的 "not in",比如 findByUsernameNotIn(Collection<String> userList) ,方法的参数可以是 Collection 类型,也可以是数组或者不定长参数;

2、使用@Query创建查询

@Query("select a from AccountInfo a where a.balance > ?1") 
 public Page<AccountInfo> findByBalanceGreaterThan( 
 Integer balance,Pageable pageable); 
 }
@Query("from AccountInfo a where a.accountId = :id") 
 public AccountInfo findByAccountId(@Param("id")Long accountId); 

   @Query("from AccountInfo a where a.balance > :balance") 
   public Page<AccountInfo> findByBalanceGreaterThan( 
 @Param("balance")Integer balance,Pageable pageable); 
 } 

此外可以使用@Query来执行更新操作,需要@Modifying来共同实现,如:

@Modifying 
 @Query("update AccountInfo a set a.salary = ?1 where a.salary < ?2") 
 public int increaseSalary(int after, int before);

3、通过调用JPA命名查询语句创建查询

命名查询是JPA提供的一种将查询语句从方法体重独立出来,以供多个方法共用的功能。Spring Data JPA对命名查询也提供了很好的支持。用户只需要按照JPA规范在orm.xml文件或在代码中使用@NamedQuery(@NamedNativeQuery)定义好查询语句,唯一要做的就是为该语句命名时,需要满足"DomainClss.methodName()"的命名规则。

public interface UserDao extends Repository<AccountInfo, Long> { 
 public List<AccountInfo> findTop5(); 
 } 
如果希望为findTop5()创建命名查询,并与之关联,我们只需要在适当的位置定义命名查询语句,并将其命名为"User.findTop5",框架在创建代理类的过程中,解析到该方法时,优先查找名为"User.findTop5"的命名查询定义,如果没有找到,则尝试解析方法名,根据方法名字创建查询。

6、Spring Data JPA对事务的支持

默认情况下,Spring Data JPA实现的方法都是使用事务的。针对查询类型的方法,其等价于@Transactional(readOnly=true);增删该类型的方法,等价于@Transactional。除了将查询方法设为只读事物外其他事物属性据采用某人值。如果用户有必要,可以在接口方法上使用@Transactional显示指定事务属性,该值覆盖Spring Data JPA提供的默认值。同时,开发者也可以在业务层方法上使用@Transacal指定事务属性,这主要针对一个业务层方法多次调用持久层方法的情况。持久层的的事务会根据设置的事务传播行为来决定是挂起事务还是加入业务层的事务。具体@Transacal的使用可以参考Spring的参考文档。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值