【java学习-Spring】Spring-data-jpa(JavaPersistenc。。。
1,概念
1)JPA
场景:整合第三⽅ORM框架,建⽴⼀种标准的⽅式ORM 访问数据库的统⼀。
现阶段JPA⼏乎都是接⼝,实现都是Hibernate在做。我们都知道,在使⽤持久化⼯具的时候,⼀般都有⼀个对象来操作数据库,在原⽣的Hibernate中叫做Session,在MyBatis中叫做SqlSession,⽽在JPA中叫做EntityManager通过这个对象来操作数据库。
对象关系映射(Object Relational Mapping,简称ORM)
通过使⽤描述对象和数据库之间映射的元数据,将⾯向对象语⾔程序中的对象⾃动持久化到关系数据库中。
2)占位符
JPA⾥占位符:?1(必须按顺序传参)或 :userName (推荐,本地sql中出现的冒号需要通过双斜杠转义)。
3)
JSR 338主要定义了如何通过普通的Java domain进⾏关系数据库的操作及映射,概括如下:
1>Entity
必须是顶级类
@Entity注解的类
必须有⼀个⽆参的public 或 protected的构造⽅法
不能是final类,且不能有final⽅法或final变量
⼀个Entity类通常与数据库的⼀张表进⾏对应
⼀个Entity实例表现为数据库的⼀条数据
对Entity的操作即对数据库的操作
⽣命周期包含初始、托管、释放、消亡
2>EntityManager
对Entity持久化操作的主要对象
通过EntityManagerFactory获取实例
⼀个实例代表⼀个数据库连接
每个线程拥有⾃⼰的EntityManager实例
主要⽅法有persist、remove、merge、createQuery、find
可使⽤@PersistenceContext注⼊
3>EntityManagerFactory
创建EntityManager的⼯⼚
EntityManagerFactory的创建成本很⾼,对于给定的数据库,系统应该只创建⼀个与之关联的Factory
可使⽤@PersistenceUnit注⼊
4> EntityTransaction
表⽰数据库事务,在增、删、改时使⽤
可通过Transaction()获取
5>Persistence Context
维护⼀组托管状态的Entity实例
与EntityManager是相关联的
6>Persistence Unit
⼀组Entity及相关设置的逻辑单元
定义创建EntityManagerFactory所需要的参数
通过l定义或者通过⼀个PersistenceUnitInfo对象
7>总结
通过Persistence Unit创建EntityManagerFactory,再通过EntityManagerFactory获取EntityManager。
2,EntityManager
EntityManager是JPA中⽤于增删改查的接⼝,它的作⽤是:对⼀组实体类(Entity Bean)与底层数据源(tabel或临时表)之间进⾏O/R 映射的管理。
1)Entity⽣命周期
状态名描述作为java对象
存在
在实体管理器中
存在
在数据库存
在
New(瞬时对象)尚未有id,还未和Persistence Context建⽴关联的对象yes no no
Managed(持久化受管对
象)
有id值,已经和Persistence Context建⽴了关联的对象yes yes yes
Detached(游离态离线对
象)
有id值,但没有和Persistence Context建⽴关联的对象no no no
Removed(删除的对象)有id值,尚且和Persistence Context有关联,但是已经准备好从数
据库中删除
yes yes no
2)⽅法
1> 新增数据:em.persist(Object entity);
如果entity的主键不为空,⽽数据库没有该主键,会抛出异常;
如果entity的主键不为空,⽽数据库有该主键,且entity的其他字段与数据库不同,persist后不会更新数据库;
2> 根据主键查数据:em.find(Class entityClass, Object primaryKey);
如果主键格式不正确,会抛出illegalArgumentException异常;
如果主键在数据库未到数据返回null;
3>删除数据:em.remove(Object entity);
只能将Managed状态的Entity实例删除,由此Entity实例状态变为Removed;
4> 将Detached状态的Entity实例转⾄Managed状态:em.merge(T entity);
5> 将所有的Entity实例状态转⾄Detached状态:em.clear();
场景举例:
从数据查出对象A
B.list=A.list
修改B.list
save(B)
最后发现往往A在数据库种的值也跟着改变了,为避免这种情况,在每次save之前em.clear() ⼀下
6> 将所有Managed状态的Entity实例同步到数据库:em.flush();
7> 刷新获得最新Entity:em.refresh(Object entity);
加载Entity实例后,数据库该条数据被修改,refresh该实例,能得到数据库最新的修改,覆盖原来的Entity实例。
8> 获取Session对象:em.unwrap(Session.class)
3)托管⽅式
A. 容器托管(EntityManger && PersistenceContext)
@PersistenceContext也可以⽤@Autowired注解。
EntityManager em;
@PersistenceContext是jpa专有的注解(推荐),⽽@Autowired是spring⾃带的注释。
@AutowiredEntityManager不是线程安全的,当多个请求进来的时候,spring会创建多个线程,⽽@PersistenceContext就是⽤来为每个线程创建⼀个EntityManager的,⽽@Autowired就只创建了⼀个,为所有线程共⽤,有可能报错。
B. 应⽤托管(EntityManagerFactory && PersistenceUnit)
EntityManagerFactory 接⼝主要⽤来创建 EntityManager 实例。该接⼝约定了如下4个⽅法:
createEntityManager():⽤于创建实体管理器对象实例。
createEntityManager(Map map):⽤于创建实体管理器对象实例的重载⽅法,Map 参数⽤于提供 EntityManager 的属性。
isOpen():检查 EntityManagerFactory 是否处于打开状态。实体管理器⼯⼚创建后⼀直处于打开状态,除⾮调⽤close()⽅法将其关闭。
close():关闭 EntityManagerFactory 。 EntityManagerFactory 关闭后将释放所有资源,isOpen()⽅法测试将返回false,其它⽅法将不能调⽤,否则将导致Ille galStateException异常。
2,原理
1)Repository接⼝
Repository
最顶层的接⼝,是⼀个空接⼝,⽬的是为了统⼀所有的Repository的类型,且能让组件扫描时⾃动识别。CrudRepository
Repository的⼦接⼝,提供CRUD 的功能。
PagingAndSortingRepository
CrudRepository的⼦接⼝, 添加分页排序。
JpaRepository
PagingAndSortingRepository的⼦接⼝,增加批量操作等。
常⽤⽅法
delete删除或批量删除
findOne查单个
findAllByIdAndName查所有
save保存单个或批量保存
saveAndFlush保存并刷新到数据库
countByInvestUserId
⽅法说明
dao.flush ()同步持久上下⽂环境,即将持久上下⽂环境的所有未保存实体的状态信息保存到数据库中。
⽤数据库实体记录的值更新实体对象的状态,即更新实例的属性值。
(Object entity)
dao.clear ()清除持久上下⽂环境,断开所有关联的实体。如果这时还有未提交的更新则会被撤消。
判断⼀个实例是否属于当前持久上下⽂环境管理的实体。
(Object entity)
dao.isOpen ()判断当前的实体管理器是否是打开状态。
()
返回资源层的事务对象。EntityTransaction实例可以⽤于开始和提交多个事务。
dao.close ()
关闭实体管理器。之后若调⽤实体管理器实例的⽅法或其派⽣的查询对象的⽅法都将抛出 IllegalstateException 异常,除了getTransaction 和 isOpen⽅法(返回 false)。不过,当与实体管理器关联的事务处于活动状态时,调⽤ close ⽅法后持久上下⽂
将仍处于被管理状态,直到事务完成。
⽅法说明
JpaSpecificationExecutor
⽤来做复杂查询的接⼝。
2)启动过程
由于引⼊了starter-data-jpa,⾃动配置,spring启动时会实例化⼀个Repositories,然后扫描包,出所有继承Repository的接⼝(除@NoRepositoryBean注解的类),遍历装配。为每⼀个接⼝创建相关实例。
SimpleJpaRespositry——⽤来进⾏默认的DAO操作,是所有Repository的默认实现
JpaRepositoryFactoryBean——装配bean,装载了动态代理Proxy,会以对应的DAO的beanName为key注册到DefaultListableBeanFactory中,在需要被注⼊的时候从这个bean中取出对应的动态代理Proxy注⼊给DAO JdkDynamicAopProxy——动态代理对应的InvocationHandler,负责拦截DAO接⼝的所有的⽅法调⽤,然后做相应处理,⽐如findByUsername被调⽤的时候会先经过这个类的invoke⽅法
导⼊jpa,⾃动配置扫描包内所有继承了Repository接⼝的接⼝,为每⼀个接⼝实例⼀个代理类(SimpleJpaRepository),并为每个⽅法确定⼀个query策略,已经其他所需的bean,使⽤⾃定的repository时,是使⽤的代理类,经过⼀些列的后,选取⼀个query执⾏器JpaQueryExecution,然后创建Query对象,拼接sql,组装参数等DB操作,最后返回ResultList()。
3,使⽤
1)maven配置以及相关数据库依赖配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>2.1.7.RELEASE</version>
springboot推荐算法</dependency>
2)实体类及注解
@Table(name=userinfoTab)
@Entity
public class Userinfo implements Serializable {
@Id //映射到数据库表的主键属性
@GeneratedValue(strategy=GenerationType.AUTO) //主键的⽣成策略(⾃增)
private Long user_id;
private String user_name;
@Column(length = 255) //配置单列属性
private String user_tel;
@Transient
private String new_time;
...
}
@Entity
声明这个类是⼀个实体类,必写。
@Table(name=userinfoTab)
指定映射到数据库的表格。
name 表名
catalog 设置表所属的数据库⽬录
schema 设置表所属的模式
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论