1. JPA是什么?
Java Persistence API:用于对象持久化的一组API。
JPA的思想就是:可以用Java代码实现的,为什么还要自己去编写sql语句?其核心的一切都是围绕如何拼接SQL语句进行的。
2、Spring Data
Spring Data 是 Spring 的一个子项目。用于简化数据库访问,支持NoSQL 和 关系型数据存储。其主要目标是使数据库的访问变得方便快捷。Spring Data 具有如下特点:
1、SpringData 项目支持 NoSQL 存储:
MongoDB (文档数据库)
Neo4j(图形数据库)
Redis(键/值存储)
Hbase(列族数据库)
2、SpringData 项目所支持的关系型数据存储技术:
JDBC
JPA
3、使用jpa需要给实体类加注解
@Entity(name = "t_book")
public class Book {
private Long id;
private String name;
private String author;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Long getId() {
return id;
}
// 省略其他getter/setter
}
@Entity注解表示这是一个实体类,那么在项目启动时会自动针对该类生成一张表,默认的表名为类名,如果使用了name属性表示自定义生成的表名。@Id注解表示这个字段是一个id,@GeneratedValue注解表示主键采用自增长策略,对于类中的其他属性,默认都会根据属性名在表中生成相应的字段,字段名和属性名相同,如果开发者想要对字段进行定制,可以使用@Column注解,去配置字段的名称,长度,是否为空等等。
4、多条件单表查询
构建谓语
Specification<Product> specification = new Specification<Product>() {
@Override
public Predicate toPredicate(Root<Product> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
Expression<String> idCol = root.get("id");
Expression<BigDecimal> rewardRateCol = root.get("rewardRate");
Expression<String> statusCol = root.get("status");
List<Predicate> predicates = new ArrayList<>();
if (idList != null && idList.size() > 0) {
predicates.add(idCol.in(idList)); //##1
}
if (minRewardRate != null && BigDecimal.ZERO.compareTo(minRewardRate) < 0) {
predicates.add(cb.ge(rewardRateCol, minRewardRate)); //##2
}
if (maxRewardRate != null && BigDecimal.ZERO.compareTo(maxRewardRate) < 0) {
predicates.add(cb.le(rewardRateCol, maxRewardRate));
}
if (statusList != null && statusList.size() > 0) {
predicates.add(statusCol.in(statusList));
}
query.where(predicates.toArray(new Predicate[0]));
return null;
}
};
Page<Product> page = repository.findAll(specification, pageable);
谓语是什么呢?按我的理解,谓语就是一个条件限定词。
1、使用Expression的in方法构建了一个包含的条件(或谓语),查询结果的id需要包含在idList里。
2、我们使用criteriaBuilder的ge方法构建了一个大于的条件(或谓语),该条件要求收益率大于指定的值。
5、自定义查询@Query的使用
@Query(value = "SELECT CONCAT_WS('|', order_id,outer_order_id,chan_id,chan_user_id,product_id,order_type,amount,DATE_FORMAT( create_at,'%Y-%m-%d %H:%i:%s')) FROM order_t WHERE order_status = 'success' AND chan_id = ?1 AND create_at >= ?2 AND create_at < ?3",nativeQuery = true)
List<String> queryVerifiableOrders(String chanId, Date start, Date end);
这里有三个参数,对应三个占位符,占位符是固定写法。还有另外一种使用命名参数的方式。nativeQuery = true
表示这里使用的是原生态的sql查询语句。
6、合法参数校验
Spring 采用一个 org.springframework.util.Assert 通用类完成这一任务。
Assert 翻译为中文为“断言”,使用过 JUnit 的读者都熟知这个概念,它断定某一个实际的运行值和预期想一样,否则就抛出异常。Spring 对方法入参的检测借用了这个概念,其提供的 Assert 类拥有众多按规则对方法入参进行断言的方法,可以满足大部分方法入参检测的要求。这些断言方法在入参不满足要求时就会抛出 。IllegalArgumentException。
常用断言方法源码分析:
public static void notNull(@Nullable Object object, String message) {
if (object == null) {
throw new IllegalArgumentException(message);
}
}
当object为null时抛出异常。
public static void isTrue(boolean expression, String message) {
if (!expression) {
throw new IllegalArgumentException(message);
}
}
当 expression 为true通过,flase时抛出异常。
7、Log4j
Log4j建议只使用四个级别,优先级从高到低分别是 ERROR、WARN、INFO、DEBUG。
通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的开关。比如在这里定义了INFO级别, 则应用程序中所有DEBUG级别的日志信息将不被打印出来。优先级高的将被打印出来。项目上生产环境时候一定得把debug的日志级别重新调为warn或者更高,避免产生大量日志。
8、配置多数据源
目标:
@Test
public void queryOrder(){
System.out.println(orderRepository.findAll());
System.out.println(readOrderRepository.findAll());
}
orderRepository.findAll()
连接的是主库、生成订单。
readOrderRepository.findAll()
连接的是从库、生成对账文件、保存渠道的订单信息。
目标定好了,如何实现呢?
有什么方法帮助自己找到答案?
9、学习经验
1、如果如果遇到不太熟悉的代码,主要通过点击方法查看源码寻找答案,JDK相关的才看官方API文档。框架相关的资料大多不完善,找文档很费时间,点击方法看看源码是怎么实现的,足以解决问题。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。