- JPQL入门须知
a) 格式:JPQL语句只能写java的类名和属性名,JPQL语句是面向对象的语句。
SQL是面向数据库表的查询语句
b) JPQL的书写规则
i. 里面不能出现表名,列名,只能出现java的类名(或类名的完全限定名),属性名是区分大小写
ii. 出现的sql关键字是一样的意思,不区分大小写
iii. 不能写select * 要写select 别名
- JPA使用JPQL简单查询数据
a) 查询特定属性:String jpql = “select o.name,o.department.name from Employee o”;
b) 通过new对象的方式查找,String jpql = "select new Employee(o.name,o.department.name) from Employee o";
c)
查询结果过滤:String jpql = "select o from Employee o where
o.department.city=? or o.department.city=?";
query.setParameter(1, "成都").setParameter(2, "广州");
d)
查询排序:String jpql = "select o from Employee o order by o.salary
desc";
关联对象排序 String jpql = "select o from Employee o order by
o.department.id desc";
e)
使用IN:String jpql = "select o from Employee o where
o.department.street IN(?0,?1)";
query.setParameter(1, "八宝街").setParameter(2, "春熙路");
f) 查询区间数据:select o from Employee o where o.salary between:min and max;
g)
Like模糊查询:String
jpql = "select o from Employee o where o.name like ? or o.name like
?";
Query query = entityManager.createQuery(jpql);
query.setParameter(1, "%er%").setParameter(2, "%en%");
h) Distinct去重:String jpql = "select distinct o.department from Employee o";
i)
New Bigdecimal(“10”)à打印10
New Bigdecimal(10)à打印一个无线接近于10的值
j) 五个聚集函数 :avg(),count(),sum(),min(),max()
- 集合操作
a)
查询出有员工的部门,相当于是查询部门的员工数量即size>0,
select o from Department o where o.employees.size>0;
b)
查询出部门信息,按照部门员工人数排序(使用函数排序)
select o from Department o order by o.employees.size desc;
c)
查询出没有员工参与的项目(对集合使用size)
select p from Project p where p.employees.size=0;
- JPQL中JSON关键字与SQL关键字的区别:SQL要写ON语句,JPQL不用写ON语句
JPQL语句on前面是对象的别名,SQL语句on前面是表名的别名
a) 查询所有员工及部门信息:String jpql = "select o,d.name from Employee o left join o.department d"; - 分页查询
a)
// 当前页码int
currentPage = 2;
// 一页显示条数int pageSize = 5;
// 从那里开始取数据,索引从0开始
int firstResult = (currentPage - 1) * pageSize;
//取多少条数据
int maxResult=pageSize
query.setFirstResult(firstResult).setMaxResults(maxResults);
- JPA使用原生SQL查询数据
a)
返回对象数组
去Query query = entityManager.createNativeQuery(sql);
List<Object[]> list = query.getResultList();
b)
返回模型对象
String sql = "select * from employee";
// 告诉hibernate把employee表转换为Employee对象
Query query = entityManager.createNativeQuery(sql, Employee.class);
List<Employee> list = query.getResultList();
添加查询条件
c) String sql = "select * from
employee where name like ? order by salary
desc";
Query query = entityManager.createNativeQuery(sql, Employee.class);
query.setParameter(1, "%en%");
List<Employee> list = query.getResultList();
- 事务并发&乐观锁、
a) 事务的四大特性
i. 原子性:对于其数据的操作,要么全部完成,要么全部失败
ii. 一致性:事务在完成是不会对数据库的约束条件发生改变
iii. 隔离性:事务并发时,各个事务是不会发生关系,互不影响
iv. 持久性:事务完成之后,它对于系统的数据的影响是永久性的。
b) 事务并发:数据库允许多个事务同时进行,提高性能
c)
事务的隔离机制:当并发事务访问或修改同一条数据的时候,通常需要采用隔开机制来解决并发问题,
d) 隔离机制的实现
i. 一些事务的并发问题
- 第一类丢失更新(秒杀活动和)
- 第二类丢失更新:多个事务同时读取相同数据,并完成各自的事务提交,导致最后一个事务提交会覆盖前面所有事务对数据的改变
- 脏读
- 幻读
- 不可重复读
脏读,幻读,不可重复读可以交给数据库管理的隔离机制来处理, - 事务的隔离级别
a) Serilazable: 脏读,幻读,不可重复读都不会出现
b) readUnconmmited: 脏读,幻读,不可重复读都会出现
c) readConmmited:防止脏读,无法避免幻读和重复读
d)
preperTable: 防止脏读、重复读,无法避免幻读
e) 悲观锁:处理同一张表的同一行同一列数据,如果一个事务没有被释放,其他事务将永远处于等待状态,使用entityManager.find(class,id,LockModeType);加悲观锁,相当于发送SELECT ... FOR
UPDATE(加了一个行锁)
使用entityManager.lock(object,LockModeType);加悲观锁,相当于发送SELECT id FROM ... FOR UPDATE(加了一个行锁)
效率低:必须等待一个事务执行完毕,才能执行其他事务
f) 乐观锁: 处理同一张表的同一行同一列数据,就是将数据的版本号不同作为条件查询
i. 使用场景:秒杀活动(使用一个注解@Version,开发时不建议使用)
ii. 场景:电商高并发,使用消息队列,
- JPA的优化
a) 使用双向一对多关联
b) 配置对象二级缓存,不使用集合二级缓存,如果使用了集合二级缓存,集合里面的对象也必须二级缓存;查询缓存(jpql查询),没有查询条件才使用查询缓存
c) 组合关系集合使用list(顺序,重复),多对多集合使用set
- 数据库三范式
a) 第一范式:表创建后的每一列数据都不能再被分开,一列只能存储一个值
b) 第二范式:每个表里面都有一个唯一的标识来区分每一行数据,即主键
第三范式:一个表里面一般不要存储其他表的非关键信息,一般存的是其他表的主键,即外键