JPA 8|学习笔记

简介: 快速学习JPA 8

开发者学堂课程【高校精品课-上海交通大学 -互联网应用开发技术JPA 8】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址:https://developer.aliyun.com/learning/course/76/detail/15761


JPA 8


内容介绍:

一、Transitive persistence

二、访问数据库

三、WEB前后台通信- AJAX 和 JSON


一、Transitive persistence

Person 和 Event 之间是多对多的关系,所以 Person 中有一个集合类的对象 List<Event> 参与活动,同样的 Event 中也有一个 List<Person> 表示参与活动的人。

如果有一部分人( Person )被删除,其所参加的活动 Event 不能删除,因为这个活动不因人不参加而不存在;反之亦然。所以二者之间不存在关联的删除、插入或者更新的动作。

特殊情况:比如一个学生( Student  )有选课的记录,如果这个学生被删除了,那么选课记录就无意义;再比如一个 Person 的 email ,如果这个 Person 被删除,那么这个 email 也无意义。

所以当学生被插入到数据库后,在内存里创建一个学生,那么在他的一个 List 类型的< Cause >中 add 一些课程,当把学生存储到数据库后,对应的选课记录也应该被插入到数据库里,这就是关联的插入。

这就是传递性的持久化( Transitive persistence ),在有关系的类之间做持久化时做出相应的动作,可以在插入的时候持久化,也可以在 Student 跟某一个 Session 关联的时候,把它相关联的选课记录都与这个 Session 关联,还有所有 Merge ,还要把它删除,并从数据库里去刷新的时候将其刷接;与 Merge 相反的动作就是 Detach ,当 Student 和 Session 要断开连接的时候,选课记录也就跟这个 Session 断开连接; All 表示以上都要有,表示要不要做关联的动作。

图片160.png

具体应用比如 Customer 下了一组订单,有一个订单的计算类,其为一对多,即一个人可以下很多订单,那在这个一对多的关系里面就要做关联操作,并且是所有都要做,所以当创建一个 Customer ,在这个Order里面写入东西时,只需要把 Customer 持久化到数据库里,它对应的 Order 就写进去了,所以找到 Customer 组件为1的用户加载进来时就直接可以做相应的一个动作,即再找到一个订单,把这个订单从 Customer 这个 Order 里删除,删除后,因为只要从 Customer 的这个集合类里把它持有的对这一个订单的引用删掉,也就是说,不用将其所在的 Order 删掉,如果想把 Order 一起删掉,那么就会执行 customer.getOrders().remove(order) ,也就是执行 Customer 更新的动作的同时会把 Order 删掉。直白的讲,对象与对象之间是用组合还是聚集,组合的概念是部分与整体的概念,如果一方被删除,那么另一方关联的也被删除;而聚集是指像 Person 和 Event ,仅是做聚集,不代表 Person 被删除了,其参与的 Event 也要删除。所以两个类之间的关系是组合还是聚集,关键在于关联的操作注意的问题。

图片161.png

完成这个大作业不需要考虑特别复杂的情况,至于这种设置可能用默认值即可,访问数据库就是通过 OR 映射的方式访问的,一个最小的基本上能够通过 OR 的工具去访问数据库,包括表和表之间存在关联情况应该怎么更复杂的东西显然会特别多细节的东西非常多,这里只是一个最小的以及它里面的体现出来的思想

这次作业要不要做 controller ,第二次迭代完成的时候肯定要有,但是这一周的作业目前如果要有对数据库操作,用一个 sol 来操作,就像上次讲的例子即可。

另外 Spring 的这个例子如果跑不了,可能有一个 resource 没设,如果设了还跑不了,那可能是其他设计对或者路径的问题,或者是用户密码等没有数据库里没有这个库,数据库里的脚本库的样子是否与其一样

Person :Person 还是 Person ,包括 personID 、 age 、 firstname 、 lastname 都没有什么变化,但是在下面增加了一个属性,

图片162.png

这个属性叫做 PersonIcon ,它是一个 PersonIcon 类型的属性,是一个 ID 和字符串,这个字符串是由图像转成 Base64 的,通过 mango DB 来映射的,正常情况下一个实体类,这里面的属性就映射成了表的字段,

图片163.png

所以有 personID 、 age 、 firstname 、 lastname 等,Person ID 映射成它去找 ID ,所以 PERSONS 这张表是在 orm sample 库中,就是这四个字段,但是 PersonIcon 不在关系数据库里,但是它又属于 person 的一部分,所以要加一个叫 Transient 的 inocation 放到其 get 方法的前面,

图片164.png

这也是 Java 的企业版,按连一个标准的 inocation ,在一个实体类里,凡是用这种标签去标注过的属性, GPA 的工具包括 Spring GPA 等就不用去托管它,不用考虑它是不是关于数据表,因为它不是。

Transient 的含义是这是一个顺时的对象,不需要去做持句化,所以它就脱离了管理,从这个地方来看再次印证类和对象的设计完全要聚焦,不需要两个一对一。

那这个 PersonIcon 从哪来呢,它是用 mango DB 去映射了,然后 mango DB的 repository 去管 PersonIcon 的数据怎么拿出来,其实就只要继承、扩展,没有写什么实际东西,只用了默认里面提供的方法,与 personrepository 一样,也不写什么东西,因为用的是 GPA repository 里面自己提供的方法,关键是在 BPU 的实现,把它组成了一个完整的 person ,通过关型数据库有personal 即 Person 中的 getOne,在这个组件就拿到了person,然后通过这个 mango DB Repository的 get by id 拿到了 icon ,这个 icon 对象是 PersonIcon 类型的对象然后把这个 PersonIcon 内容取出来因为他在这个 optional 里面包了。

调用 person.setIcon ,即 setIcon 方法现在的Person为大 Icon ,然后在之上可以知道用 setIcon 设了一个 Icon ,或者为空表示。这个人在 mango DB 里找不到最后一个 person 一旦到了这一层,已经把这个具体的数据怎么存储完全屏蔽。

图片165.pngService

现在来看service,就直接调 findOne ,就得到了一个完整的Person。

图片166.png

然后再到前台 Controller ,就把这个调用service的findPersonByid 就得到了一个person,然后把这个person 转成这次的对象就返回。

图片167.png

所以可以看到在高层代码里面,是不知道person是怎么成的,可以看到这是一个完整的person对象

页面设计中有一个需要输入想找谁然后底下一个icon的地方,位置现在是为空的

图片168.png

然后发送请求:

图片169.png

后台之后它会返一个结果返回来之后就去把 name,age,icon 都给它替换。

就把这三个标签的值替换成从后台拿回来的这个数据里的 firstname, age,personicon ,里面那个叫做 iconbase 有4个值,Personicon 有两个关键属性。

图片170.png

转化成2号时需跑个应用:图片171.png

当然前提是跑这个必须要把 mango DB 先跑起来

获取二号人物:

图片172.png

获取一号任务曹操(图片未做大小处理):

图片173.png

可以看到所有的人的信息在 mango DB 里面有一部分在

强调一点就是在person这个类里,如果不想有一些属性并不是来自于关型数据库,但是从面向对象的角度来说一个人他确实是有 Id ,年龄姓名以及图标的这是一个完整的一个person的概念。可以在这个类里面把这种不需要 Hibernate或者是 Spring GPA托管的这种属性一个 Transient  

Transient 、 Hibernate或者是 Spring GPA看到之后就不管了我们就需要做如上处理。

例子放在了课件14:

图片174.png

按照PPT内容下载并运行一个 Mongo 并填充相应数据、图片。

效果如下:

图片175.png

也可以用代码处理,将数据图片写进去。

强调的是说,实体类里未必所有的属性全部要靠一个工具来托管,也可以包括用 Transient 。

 

二、访问数据库

1、Reference:

用原生的 JDBC 接口访问数据库,反映下来,现在很少有人用这种方式访问数据库。

内容包括:JNDI 较难理解

图片176.png


2、 用 JDBC 接口访问数据库:资源占用少,性能高

⑴ JDBC 接口访问数据库背景:有一个数据库,用 Tomcat 方式把数据拿回来,变成一个个对象,用代码操作这些对象,代码也许会存在,在这里面改写的这个对象,但还没有写回去造成不一致的情况,原因是从概念上讲这种方式叫 offline ——离线方式,把数据拿回本地做,离开了数据库叫离线方式。

JDBC 是在读取中有一种方式下到数据库里面去查找数据,反映可知是条数据,这条数据满足查询条件,再访问第一条,就看到目标对象了,然后如果有人改写了后面几条,当在遍历到第二条的时候,看到的就是改写过之后的状态。如果把数据拿到 Tomcat 中看,是看不到人家改写过的状态。能看到的这种状态,就叫做在线方式( online )。这是 Tomcat 与 JDBC 很大的一个差异。在线方式可以避免离线时看不到改写后的状态造成不一致的情况。

把数据拿过来都是一个一个对象,和把这些数据一次性拿回来,变成一个表格相比,它的内存占用比变成对象要小得多。直接操作 JDBC 的驱动,由驱动翻译完之后操作数据库,中间再加一个 hibernate 效率会很高。很显然,直接用 JDBC 访问比拿回来之后组一堆对象,资源占用要少一些,它的性能要高一些。

⑵ JDBC 读取还是 ORM ,哪一个更好?

需求1:列出某个学期所有学生的选课记录。它可以是一个大记录集,从数百万个记录中选择超过150000个记录。—— JDBC 读取

用 ORM 意味着要建立十几万个对象,用 Paging (分页)也需要建立十几万个对象,在这种情况下就会发现用 JDBC 直接读取的性能会好一些。

图片177.png

需求2:为了得到所有本科生的平均年龄 。——无论 JDBC 还是 ORM都要依赖 DB Function

一个最简单的方法,性能最高的方法是在数据库里面放一个 Function 如果认为不需要列一个 Function ,因为已经有 average ,但是正常的处理应该是这个function,这个function就在数据库里执行,执行完之后,返一个年龄,而不是把这15万条都拿回来,然后自己建立他的年龄去加载处理,也就是说不能把这15万条数据全取回来,因为需求是平均年龄,这件事情完全可以依赖于数据库的函数来实现。在这种情况下,就会发现,用函数调用返一个值,比拿15万条记录回来,自己去计算要快。所以在写Web应用的时候或者其他应用的时候,也是类似的一个基本的原则是处理,一定要靠近数据,越近越好。在数据库里面调它的函数总比在 Tomcat ,在另外一个进程里面去数据库,把数据传回来的处理要好,越近,就说明你需要的网络开销或者其他的开销越小。那在这种情况下就会看到用 JDBC 直接调一个函数,比用hibernate 和ORM要快。

需求3:确保数据库可以从ORACLE迁移到DB2 —— ORM

这涉及到在前面配置的时候,就出现了Dialogue这个方言的问题。也就是说circle的标准,实际上遵循的并不好。不同的数据库他们互相之间的这个circle是之间有一定差异。举例说明:到底是单引号还是双引号再扩一个字符串来表示就不一样。这个迁移在 JDBC 里面是直接要写最后一句的,将来想做这种迁移就比较困难,但是用ORM设计比较简单。回想一下在之前所讲内容,访问数据库里面,从来没有出现具体的一条 circle 语句,是靠 hibernate 或者是 Spring 这样的工具来把操作给映射成了 circle 语句,所以从这个角度来讲 ORM 映射会更好。


3、总结:

在某一些以列表为主的场景,用 JDBC 直接读取好。

在某一些要考虑到代码可维护性可迁移性作用用 ORM 映射

在某一些涉及到异常复杂的计算并且是大量数据的异常复杂的计算的情况下在数据库本地存储过程或者函数比较好。

解决方法不能单一,用 ORM 映射不能所有场景下全用 ORM 映射,要根据具体场景具体分析,目前为止所讲内容用 ORM 映射, JDBC 可以自行观看学习。

至于函数求值过程,确实会带来一系列的问题,但要辩证看。碰上复杂操作的时候,用它未必不可以。没有单一的解决方案,需求驱动,按照不同的需求具体去操作。目前课不用考虑这么复杂的场景,就用 ORM 映射的方式操作数据库就可以

那至于是 hibernate 还是 spring  JPA ,还是刚才的,其实都是 java 企业版的, java 企业版里面的 JPA 的规范的一个实现,所以在那个实体类的写法几乎一样,它俩不一样是在之上。也就是 Spring JPA 会有 JPA Report 这样的东西包好了,可以来做一些操作,其实 hibernate 那边也有类似的接口,只不过没有详细讲,然后看到这些配置数据源的方式不一样。但是Entity这个类本身包括怎么映射成表,跟其他的表之间的关联关系是怎么去做映射的,然后它的一对多、多对多的关系怎么做映射、它的主键的生成策略,包括他哪一些的属性不需要进行托管等等。这些全部都是 Java 企业版的 GPA 规定,所以在描述的时候是一模一样。

 

4、为什么要有 mango DB 的数据库?

那原因是因为从数据库的角度来说,现在看到的 no circle 的数据库越来越多。甚至会在很多情况下、在很多场景里面,会发现人家只用到了 no circle 数据库。所以从这个意义上来说,如果只会官型数据库会有所欠缺,所以必须要讲 mango DB 。

但是课程的容量是有限,要让大家去在这个里面去实践,所以讲的比较简单,就讲讲 mango然后在你的例子里面能应用它就可以。要注意的一点是 no circle代表没有 circle,一再强调的说,叫做 not only circle 就是说circle 比,不仅仅只是 circle 

最后要告诉大家,在一个系统里面数据绝对不是说只存在一个数据库里就结束了,这里指的一个是指的一种。不是只存在这个关系型的这个数据库里就可以了。可能还需要 mango ,还需要有这个全力搜索的引擎。

未来的一个系统的形态,它可能会存很多很多不同的数据在不同的数据库里出现。所以在课堂里先让大家去感受一下在两个数据库里存储数据是什么样子,所以就像前面内容中的刘备,曹操,孙权。从前端看到的就是获取这个人信息,但它实际上它的信息在两个库里。

在这个大作业里面,一定要用 ORM 映射的方式去访问数据库,而且从目前来看课程学习需求应该用 ORM 映射都能满足。所以不把这个做过多发,就用工具去实现对数据库的访问就可以了。

 

三、WEB前后台通信- AJAX 和 JSON

1、前后端在进行通信的时候是两个独立的工程,一个是在 localhost 3000这个端口上,一个在 localhost 8080这个端口上,两个端口要相通,从安全的角度来说,这叫跨预防,理论上来说就是被安全禁止,所以这里面除了要通,还涉及到一个跨域的问题。

通信 Service就可以实现前后端的一个通信它在前端写一页面里面会有产生很多动作些动作就触发后面的 Service 的处理后面是为了在它的响应里面会写进去结果,比如说它的响应一个页面于是我们的前面就看到页面,好像实现了一次跳转,但现在,前段是react页面之间的跳转逻辑,被react rooter给接管实际上我们只是想从后端拿数据要求一个完整的页面拿回来数据之后我们通过react比如set state这样的方法去更新前端然后它自动就重绘了看起来就得到了一个新的一个页面看起来就这个效果所以就不是用 Service 处理不是用 Service 来直接在响应里面写进去一个完整的页面是只写进去一个数据这个数据会传到前端由前端来决定页面

在课件中涉及前后端怎么互通:图片178.png

图片181.png

将两个同时跑起来就可以看到书中例子。然后在这里面会一系列的不足:包括特殊字符,怎么显示跨越等等,这些内容解决方法都在课件中有所展示。

2、前端和后端是通过 AJAX 来进行通信的,然后前后端传递的数据,不需要 Service直接写一个完整的页面,它只需要写进去想要的数据就可以了。

这个数据拿到前端以后,由react进行处理。那这个数据的格式适用的 Json 表示,所以 AJAX 和 Json 里面的这个 J 和这个 Js 的表示是JavaScript 。所以这之间是有必然的联系。

 

3、AJAX 是异步 JavaScript 和 XML 。

同步:发一个请求,要等待服务器的响应结束后才能发第二个请求,这个过程是十分卡顿的。异步:发一个请求后,无需等待服务器的响应,然后就可以发第二个请求。

图片179.png

同步调用:调用 a 对象上的 m 这个方法 m 在没有返回之前,这个代码是执行不下去的,调用 b 对象上的 n 方法。在 a  m 方法没有结束没有返回之前, b 对象上的 n 方法这行代码是没有办法进行执行。只能等 a  m 结束。

异步调用:a对象上的 m 这个方法, m 没有执行完之前,就可以调 b 对象上的 n 方法。实际上调这个m方法,就告诉,如果要是结束了,就返回去调用本地的一个回函数,那就知道处理完了,在这个函数里去拿结果去做处理。

AJAX 世界里面前后端通信的时候,都用得是一种异步的方式也就是当去抓后台数据的时候,前端不影响它对其他的响应,比如这里有一个输入的文本框我在这里写了很多字,我点提交,在提交的时候,在这里面还可以追加,或者在旁边还有一个文本框还可以写,而不是一点提交页面卡死不能动,一直等到提交完才能动。

在我提交的同时他去提交,把这个东西拿走以后放到后台,然后直到提交成功还是失败,在整个过程当中我前还可以在其他地方去做其他的事情比如说在这里输入,有一段脚本在一直在检查输入的语法,仍然可以运行检查错误,这就是异步通信的一个优势。

传统的Web页面的更新是在更新它的内容的时候它的页面 reload ,就是在这个页面上,比如说这个链接,点击后转成空白,然后把内容显示也就是说用户在当前页面上正在做的东西可能会丢失。或者当网速比较慢,这个刷新的过程会持续空白,不断刷新,给用户的体验非常差,刷新时间很长,效率不高。所以才出现了 AJAX 。

如果什么框架都不用,在浏览器里面的支持一个叫做 XMLHttpRequest  XHR  对象。通过它可以来发送这个 AJAX 的请求。

通过它来发整个页面,就不需要刷新完整的页面只需要发请求发送一个数据,用户拿到数据以后去刷新这个页面里头对应的那一小块当在这个地方点提交的时候,只会把这部分的内容提交掉,提交完以后显示提交成功。

要达到这样一个效果只刷新这一行内容,其他地方都不动。

逻辑为:

图片180.png

客户端页面会发出一个这样的请求,用 XML 发一个请求,这个请求到达外部端——服务端。服务端还是跟以前一样有一个servant或者是 spring controller 在这里来接收这个 request 

但是现在就不需要在这个响应里面放进一个完整页面,只发一个数据出来了。虽然它叫 XMLHttpRequest但现在已经不是一定要发一个 XML 的数据。它可以是个 Jsoy 数据。

这些数据回调就拿到了这个数据,它可以调之前看到的这次的脚本,去把某一个局部的去给它刷新掉,就是把它里面内容替换掉。这就是 AJAX 的一个运行原理。

最重要的前后端之间传递的不是完整的页面,而只是一个数据。而且它是异步调用,所以系统性能变高了,用户体验变好了。

相关文章
|
7月前
|
数据采集 容器
xpath实战
xpath实战
33 0
|
存储 前端开发 JavaScript
JPA 7|学习笔记
快速学习 JPA 7
93 0
 JPA 7|学习笔记
|
存储 前端开发 Java
JPA 6|学习笔记
快速学习JPA 6
128 0
JPA 6|学习笔记
|
存储 SQL 前端开发
JPA3|学习笔记
快速学习JPA3
127 0
JPA3|学习笔记
|
SQL 前端开发 Java
JPA2|学习笔记
快速学习JPA2
79 0
JPA2|学习笔记
|
存储 Java 关系型数据库
JPA1|学习笔记
快速学习JPA1
114 0
JPA1|学习笔记
|
存储 前端开发 NoSQL
JPA 5|学习笔记
快速学习JPA 5
111 0
JPA 5|学习笔记
|
存储 自然语言处理 开发者
WhitespaceAnalyzer|学习笔记
快速学习 WhitespaceAnalyzer
63 0
WhitespaceAnalyzer|学习笔记
|
机器学习/深度学习 存储 人工智能
GraphLearn on PAI|学习笔记
快速学习 GraphLearn on PAI。
103 0
GraphLearn on PAI|学习笔记
|
物联网 Linux 开发者
Pause|学习笔记
快速学习 Pause
82 0
Pause|学习笔记

热门文章

最新文章