Spring-data-jpa应用讲解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35977237/article/details/79870229
1.Jpa api
persistence: 最主要的是获取entitymanagerFactory
entitymanagerFactory:获取EntityManager实例
2.entitymanager:
•createQuery (String qlString):创建一个查询对象。
•createNamedQuery (String name):根据命名的查询语句块创建查询对象。参数为命名的查询语句。
•createNativeQuery (String sqlString):使用标准 SQL语句创建查询对象。参数为标准SQL语句字符串。
•createNativeQuery (String sqls, String resultSetMapping):使用标准SQL语句创建查询对象,并指定返回结果集 Map的 名称。
3.EntityTransaction
•EntityTransaction 接口用来管理资源层实体管理器的事务操作。通过调用实体管理器的getTransaction方法 获得其实例。
•begin ()
–用于启动一个事务,此后的多个数据库操作将作为整体被提交或撤消。若这时事务已启动则会抛出 IllegalStateException 异常。
•commit ()
–用于提交当前事务。即将事务启动以后的所有数据库更新操作持久化至数据库中。
•rollback ()
–撤消(回滚)当前事务。即撤消事务启动后的所有数据库更新操作,从而不对数据库产生影响。
•setRollbackOnly ()
–使当前事务只能被撤消。
•getRollbackOnly ()
–查看当前事务是否设置了只能撤消标志。
•isActive ()
–查看当前事务是否是活动的。如果返回true则不能调用begin方法,否则将抛出 IllegalStateException 异常;如果返回 false 则不能调用 commit、rollback、setRollbackOnly 及 getRollbackOnly 方法,否则将抛出 IllegalStateException 异常。
4.1.双向一对多及多对一映射
•双向一对多关系中,必须存在一个关系维护端,在 JPA 规范中,要求  many 的一方作为关系的维护端(owner side), one 的一方作为被维护端(inverse side)。
•可以在 one 方指定 @OneToMany 注释并设置 mappedBy 属性,以指定它是这一关联中的被维护端,many 为维护端。
•在 many 方指定 @ManyToOne 注释,并使用 @JoinColumn 指定外键名称
4.2. 双向一对一映射
•基于外键的 1-1 关联关系:在双向的一对一关联中,需要在关系被维护端(inverse side)中的 @OneToOne 注释中指定 mappedBy,以指定是这一关联中的被维护端。同时需要在关系维护端(owner side)建立外键列指向关系被维护端的主键列。
6. javax.persistence.Query
•Query接口封装了执行数据库查询的相关方法。调用 EntityManager 的 createQuery、create NamedQuery 及 createNativeQuery 方法可以获得查询对象,进而可调用 Query 接口的相关方法来执行查询操作。
Query接口的主要方法
–int executeUpdate()
•用于执行update或delete语句。
–List getResultList()
•用于执行select语句并返回结果集实体列表。
–Object getSingleResult()
•用于执行只返回单个结果实体的select语句。
–Query setFirstResult(int startPosition)
•用于设置从哪个实体记录开始返回查询结果。
–Query setMaxResults(int maxResult)
•用于设置返回结果实体的最大数。与setFirstResult结合使用可实现分页查询。
–Query setFlushMode(FlushModeType flushMode)
•设置查询对象的Flush模式。参数可以取2个枚举值:FlushModeType.AUTO 为自动更新数据库记录,FlushMode Type.COMMIT 为直到提交事务时才更新数据库记录。
–setHint(String hintName, Object value)
•设置与查询对象相关的特定供应商参数或提示信息。参数名及其取值需要参考特定 JPA 实现库提供商的文档。如果第二个参数无效将抛出IllegalArgumentException异常。
–setParameter(int position, Object value)
•为查询语句的指定位置参数赋值。Position 指定参数序号,value 为赋给参数的值。
–setParameter(int position, Date d, TemporalType type)
•为查询语句的指定位置参数赋 Date 值。Position 指定参数序号,value 为赋给参数的值,temporalType 取 TemporalType 的枚举常量,包括 DATE、TIME 及 TIMESTAMP 三个,,用于将 Java 的 Date 型值临时转换为数据库支持的日期时间类型(java.sql.Date、java.sql.Time及java.sql.Timestamp)。
–setParameter(int position, Calendar c, TemporalType type)
•为查询语句的指定位置参数赋 Calenda r值。position 指定参数序号,value 为赋给参数的值,temporalType 的含义及取舍同前。
–setParameter(String name, Object value)
•为查询语句的指定名称参数赋值。
–setParameter(String name, Date d, TemporalType type)
•为查询语句的指定名称参数赋 Date 值。用法同前。
–setParameter(String name, Calendar c, TemporalType type)
•为查询语句的指定名称参数设置Calendar值。name为参数名,其它同前。该方法调用时如果参数位置或参数名不正确,或者所赋的参数值类型不匹配,将抛出 IllegalArgumentException 异常。
7. select语句
select_clause
form_clause
[where_clause]
[groupby_clause]
[having_clause]
[orderby_clause]
8.select-from 子句
•from 子句是查询语句的必选子句。
–Select 用来指定查询返回的结果实体或实体的某些属性
–From 子句声明查询源实体类,并指定标识符变量(相当于SQL表的别名)。
•如果不希望返回重复实体,可使用关键字 distinct 修饰。select、from 都是 JPQL 的关键字,通常全大写或全小写,建议不要大小写混用。
9. 查询所有实体
•查询所有实体的 JPQL 查询字串很简单,例如:
  select o from Order o 或  select o from Order as o
•关键字 as 可以省去。
•标识符变量的命名规范与 Java 标识符相同,且区分大小写。
10. 查询所有实体
•调用 EntityManager 的 createQuery() 方法可创建查询对象,接着调用 Query 接口的 getResultList() 方法就可获得查询结果集。例如:
•Query query = entityManager.createQuery( "select o from Order o");
•List orders = query.getResultList();
•Iterator iterator = orders.iterator();
•while( iterator.hasNext() ) {
  // 处理Order
}
11. where子句
•where子句用于指定查询条件,where跟条件表达式。例:
  select o from Orders o where o.id = 1
  select o from Orders o where o.id > 3 and o.confirm = 'true' 
  select o from Orders o where o.address.streetNumber >= 123
•JPQL也支持包含参数的查询,例如:
  select o from Orders o where o.id = :myId
  select o from Orders o where o.id = :myId and o.customer = :customerName
 注意:参数名前必须冠以冒号(:),执行查询前须使用Query.setParameter(name, value)方法给参数赋值。
•也可以不使用参数名而使用参数的序号,例如:
select o from Order o where o.id = ?1 and o.customer = ?2
–其中 ?1 代表第一个参数,?2 代表第一个参数。在执行查询之前需要使用重载方法Query.setParameter(pos, value) 提供参数值。
Query query = entityManager.createQuery( "select o from    Orders o where o.id = ?1 and o.customer = ?2" );
query.setParameter( 1, 2 );
query.setParameter( 2, "John" );
List orders = query.getResultList();
… …
•where条件表达式中可用的运算符基本上与SQL一致,包括:
–算术运算符:+ - * / +(正) -(负)
–关系运算符:== <> > >= < <= between…and like in is null 等
–逻辑运算符: and or  not
•下面是一些常见查询表达式示例:
// 以下语句查询 Id 介于 100 至 200 之间的订单。
select o from Orders o where o.id between 100 and 200
// 以下语句查询国籍为的 'US'、'CN'或'JP' 的客户。
select c from Customers c where c.county in ('US','CN','JP')
// 以下语句查询手机号以139开头的客户。%表示任意多个字符序列,包括0个。
select c from Customers c where c.phone like '139%'
// 以下语句查询名字包含4个字符,且234位为ose的客户。_表示任意单个字符。
select c from Customers c where c.lname like '_ose'
// 以下语句查询电话号码未知的客户。Nul l用于测试单值是否为空。
select c from Customers c where c.phone is null
// 以下语句查询尚未输入订单项的订单。empty用于测试集合是否为空。
select o from Orders o where o.orderItems is empty
12. 查询部分属性
•如果只须查询实体的部分属性而不需要返回整个实体。例如:
select o.id, o.customerName, o.address.streetNumber from Order o order by o.id
•执行该查询返回的不再是Orders实体集合,而是一个对象数组的集合(Object[]),集合的每个成员为一个对象数组,可通过数组元素访问各个属性。
13. 使用 Hibernate 的查询缓存
String jpql="select c from cust c"
Query query =entityManager.createQuery(jpql);
query.setHint(QueryHints.CACHEABLE,false);
14. order by子句
•order by子句用于对查询结果集进行排序。和SQL的用法类似,可以用 “asc“ 和 "desc“ 指定升降序。如果不显式注明,默认为升序。
select o from Orders o order by o.id
select o from Orders o order by o.address.streetNumber desc
select o from Orders o order by o.customer asc, o.id desc
15.group by子句与聚合查询
•group by 子句用于对查询结果分组统计,通常需要使用聚合函数。常用的聚合函数主要有 AVG、SUM、COUNT、MAX、MIN 等,它们的含义与SQL相同。例如:
select max(o.id) from Orders o
•没有 group by 子句的查询是基于整个实体类的,使用聚合函数将返回单个结果值,可以使用Query.getSingleResult()得到查询结果。例如:
Query query = entityManager.createQuery(
  "select max(o.id) from Orders o");
Object result = query.getSingleResult();
Long max = (Long)result;
16. having子句
•Having 子句用于对 group by 分组设置约束条件,用法与where 子句基本相同,不同是 where 子句作用于基表或视图,以便从中选择满足条件的记录;having 子句则作用于分组,用于选择满足条件的组,其条件表达式中通常会使用聚合函数。
•例如,以下语句用于查询订购总数大于100的商家所售商品及数量:
select o.seller, o.goodId, sum(o.amount) from V_Orders o group by
o.seller, o.goodId having sum(o.amount) > 100
•having子句与where子句一样都可以使用参数。
17. 关联查询
•在JPQL中,很多时候都是通过在实体类中配置实体关联的类属性来实现隐含的关联(join)查询。例如:
select o from Orders o where o.address.streetNumber=2000
•上述JPQL语句编译成以下SQL时就会自动包含关联,默认为左关联。
•在某些情况下可能仍然需要对关联做精确的控制。为此,JPQL 也支持和 SQL 中类似的关联语法。如:
–left out join / left join
–inner join
–left join / inner join fetch
–其中,left join和left out join等义,都是允许符合条件的右边表达式中的实体为空。
•例如,以下外关联查询可以找出所有客户实体记录,即使它未曾订货:
select c from Customers c left join c.orders o
•以下内关联查询只找出所有曾订过商品的客户实体记录:
select c from Customers c inner join c.orders o
•如果001号客户下过5次订单的话,以下fetch关联查询将得到 5个客户实体的引用,并且执行了 5 个订单的查询:
select c from Customers c left join fetch c.orders o where c.id=001
18. JPQL函数
•JPQL提供了以下一些内建函数,包括字符串处理函数、算术函数和日期函数。
•字符串处理函数主要有:
–concat(String s1, String s2):字符串合并/连接函数。
–substring(String s, int start, int length):取字串函数。
–trim([leading|trailing|both,] [char c,] String s):从字符串中去掉首/尾指定的字符或空格。
–lower(String s):将字符串转换成小写形式。
–upper(String s):将字符串转换成大写形式。
–length(String s):求字符串的长度。
–locate(String s1, String s2[, int start]):从第一个字符串中查找第二个字符串(子串)出现的位置。若未找到则返回0。
•算术函数主要有 abs、mod、sqrt、size 等。Size 用于求集合的元素个数。
•日期函数主要为三个,即 current_date、current_time、current_timestamp,它们不需要参数,返回服务器上的当前日期、时间和时戳。
19. update语句
•update语句用于执行数据更新操作。主要用于针对单个实体类的批量更新
•以下语句将帐户余额不足万元的客户状态设置为未偿付:
update Customers c set c.status = '未偿付' where c.balance <
10000
20. delete语句
•delete语句用于执行数据更新操作。
•以下语句删除不活跃的、没有订单的客户:
delete from Customers c where c.status =
'inactive' and c.orders is empty
21.JPA-query-unwrap
返回mapEclipseLink的query.setHint(QueryHints.RESULT_TYPE, ResultType.Map); 
Hibernate的.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);

所以,如果我们想要返回Map并且确定底层用的是某一种JPA的实现时我们可以退而求其次, 牺牲跨实现的特性来满足我们的需求:
  1. public void testNativeQuery(){  
  2.     Query query = entityManager.createNativeQuery("select id, name, age from t_user");  
  3.     query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);  
  4.     List rows = query.getResultList();  
  5.     for (Object obj : rows) {  
  6.         Map row = (Map) obj;  
  7.         System.out.println("id = " + row.get("ID"));  
  8.         System.out.println("name = " + row.get("NAME"));  
  9.         System.out.println("age = " + row.get("AGE"));  
  10.     }  
  11. }  

这里需要注意的是, 用Map肯定要比用Object数组来的效率低。所以你要看性能下降是否在可接受范围内。再就是在我的Hibernate 4.2.x的环境下,无论你原生SQL中写的是大写字母还是小写字母,返回的字段名都是大写的。当然你可以通过自定义ResultTransformer的形式对字段名进行一定的处理, 甚至是返回自己需要的POJO。


猜你喜欢

转载自blog.csdn.net/qq_35977237/article/details/79870229
今日推荐