依赖
<!-- JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- WEB -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- ORACLE,直接导入不起作用,下jar文件打包成maven的坐标 -->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.3</version>
</dependency>
配置文件
spring.datasource.url=jdbc:oracle:thin:@ip:port:orcl
spring.datasource.username=111
spring.datasource.password=111
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
spring.jpa.hibernate.ddl-auto=create
#create每次都会重新创建数据库表,update有表不会重新创建会刷新字段,没有表会重新创建表。
spring.jpa.show-sql=true
#打印执行的SQl
实体
@Entity,作用在类上,表示与数据库的表(默认类名)映射。可以使用name指定表。
@Table,作用在类上,表示指定数据库的表,跟@Entity的name属性功能差不多。
@Id,作用在属性上,标识该属性是主键,与数据库表的主键对应。(一般都得写)
@Column,作用在属性上,标识该属性是普通属性与数据库表字段对应(默认属性名对应,属性名驼峰命名和表的字段下划线命名可以对应),可以用name属性指定与数据库表字段的对应。(属性名跟表的字段名对应可以不写)
Mysql主键生成策略:
@GeneratedValue():整形自增。
Oracle主键生成策略:
整形,序列的方式:
@GeneratedValue(generator = "sequenceGenerator")//随便写个主键策略名称
@GenericGenerator(
name = "sequenceGenerator", //与上边对应
strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",//主键生成策略
parameters = {
@Parameter(name = "sequence_name", //传递参数(sequence_name表示创建序列)
value = "SEQ_CUSTOMER_ID")//序列名称,ddl为update或者create时自动创建
}
)
字符串主键,uuid的方式:
@GenericGenerator(name="sequeneceGenerator",strategy="uuid")
@GeneratedValue(generator="sequeneceGenerator")
表的联系,一对多:
* 1.声明关系
* @ManyToOne or @OneToMany
* targetEntity:对方字节码对象
* 2.配置外键
* @JoinColumn
* name:在多的一方生成数据库的外键名称
* referencedColumnName:自己表的主键名称(外键数据来源)
* 3.放弃外键维护
* mappedBy:去掉外键维护后应该指定与关联对象的属性名称
* 4.级联操作
* cascade:表示执行什么操作时,的级联操作
* 1.删除:删除所有关联对象
* 2.查找:查找关联对象
* ...
* 注意:一的那边放弃外键维护
一的实体配置:
@OneToMany(targetEntity=Order.class,mappedBy="customers",cascade=CascadeType.ALL)
private List<Order> orders;
多的实体配置:
@ManyToOne(targetEntity = Customer.class)
@JoinColumn(name = "customer_id", referencedColumnName = "id")
private Customer customers = new Customer();
持久层Repository
* JpaRepository<实体类名称,主键类型>
* 继承JpaRepository这个接口,这个类已经放到spring容器中了。
* JpaRepository内置了数据库表的操作函数
public interface CustomerRepository extends JpaRepository<Customer, Long> {
* 自定义sql语句
* nativeQuery=true,开启原生sql查询
* Paramz指定参数名称
* @Modifying 允许修改(增删改要加)
* @Transactional开启事务,注意是org.springframework.transaction.annotation.Transactional
@Query(value="select l.id,l.age,l.create_time,l.name from L_TEST l where l.age>:age",nativeQuery=true)
List<Customer> findByMinAge(@Param("age")Integer age);
}
服务层ServiceImpl
第一步:加个@Service把类放到spring容器中去。
介绍持久层的函数。
save(entity):保存或者更新一个对象,当entity没有主键时新增数据并且将数据库自增的主键返回到entity中,有主键时更新数据。
deleteById(id):根据id删除一条数据,id不存在抛出异常。
findById(id):根据id查找数据,数据库id不存在跑出异常。一般用法:
* 表示根据id查找数据,查不到返回null。
Order order = orderRepository.findById(id).orElse(null);
findAll():查全部。
JPA的语法规则
JPA会根据函数的名称去执行特定的语法规则,非常的方便快捷。
1.按实体的字段查询(注意驼峰)
findBy(第一个条件)And(第二个条件)***
* 查询指定年龄的用户
List<User> findByAge(String age);
* 查询指定年龄和指定名称的用户
List<User> findByAgeAndName(String age,String name);
2.in条件查询
findBy(条件)In
* 查询用户id在ids中的用户
List<User> findByIdsIn(List<String> ids);
* 查询用户id在ids中并且指定名称的用户
List<User> findByIdsInAndUserName(List<String> ids,String name);
JPA过滤查询
实体:
@Entity
@Table(name = "T_ARTICLE")
public class Article {
@Id
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "uuid")
private String id;
private String code;
private Timestamp createTime;
private Boolean flag;
@OneToOne(optional=true)
@JoinColumn(name="school_id", unique=false, nullable=true, updatable=true)
private School school;
}
持久层:
public interface ArticleRepository extends JpaRepository<Article, String>, JpaSpecificationExecutor<Article> {
}
构造过滤条件:
public Specification<Article> getSpecificationByParams(String id,String code,Timestamp createTime,Boolean flag){
return new Specification<Article>() {
private static final long serialVersionUID = 1L;
@Override
public Predicate toPredicate(Root<Article> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
//去重查询
query.distinct(true);
List<Predicate> predicates = new ArrayList<Predicate>();
//or条件空值判断
predicates.add(cb.or(cb.isFalse(root.<Boolean>get("flag")),cb.isNull(root.get("delFlag"))));
//等值判断
if(null != code&& !"".equals(code)) {
predicates.add(cb.equal(root.<String>get("code"), code));
}
//or 条件
if(null != code && !"".equals(code)) {
String[] codes = code.split("-");
List<Predicate> preOr = new ArrayList<Predicate>();
for (String c: codes) {
preOr.add(cb.equal(root.<String>get("c"), c));
}
Predicate[] pr = preOr.toArray(new Predicate[]{});
predicates.add(cb.or(pr));
}
//大于等于
if(null != startTime) {
predicates.add(cb.greaterThanOrEqualTo(root.<Timestamp>get("updateTime"), createTime));
}
//小于
if(null != endTime) {
predicates.add(cb.lessThanOrEqualTo(root.<Timestamp>get("updateTime"), createTime));
}
//模糊查询
if(null != code && !"".equals(code)) {
predicates.add(cb.like(root.<String>get("code"), "%"+code+"%"));
}
//多表关联
Subquery<String> articleSemiQ = getMagazineFavTypeSubquery.(query,cb,creditCode)
//若是配置对象
predicates.add(root.<Long> get("school").get("id").in(schoolId));
predicates.add(root.get("id").in(articleSemiQ));
//返回结果
return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
}
};
}
public Subquery<String> getMagazineFavTypeSubquery(CriteriaQuery<?> query, CriteriaBuilder cb, String code) {
//设置返回值类型
Subquery<String> semiQ = query.subquery(String.class);
//实体类
Root<Favoriten> semiRoot = semiQ.from(Favoriten.class);
//返回字段
semiQ.select(semiRoot.get("id"));
//设置过滤条件
List<Predicate> subQPredicates = new ArrayList<>();
subQPredicates.add(cb.equal(semiRoot.get("code"), code));
//返回值
semiQ.where(subQPredicates.toArray(new Predicate[subQPredicates.size()]));
return semiQ;
}
添加分页条件:
1.单个分页
PageRequest pageParam = PageRequest.of(pageNum,pageSize,Sort.by(Direction.DESC,"updateTime"));
2.多个分页
List<Order> sortlist = new ArrayList<>();
sortlist.add(new Order(Direction.DESC,"publishTime"));
sortlist.add(new Order(Direction.ASC, "typeId"));
sortlist.add(new Order(Direction.DESC, "issue"));
Sort sort = Sort.by(sortlist);
Pageable pageParam = PageRequest.of(pageNum, pageSize, sort);
查询结果:
Page<Article> articlePages = this.articleRepository.findAll(specification, pageParam);
调用存储过程
@PersistenceContext
private EntityManager em;
String a = "";
String b = "";
boolean result = true;
Query query = em.createNativeQuery("{call tmp_test(:p1,:p2)}");
query.setParameter("p1", a);
query.setParameter("p2", b);
query.executeUpdate();