Commit 9ac948f81dca4ee6fc9764405fa67f9e3a81fa9a
1 parent
ef52bdc52f
Exists in
master
post tp1
Showing 4 changed files with 640 additions and 4 deletions
cours-03.html
View file @
9ac948f
... | ... | @@ -9,7 +9,7 @@ |
9 | 9 | |
10 | 10 | <meta name="author" content="Rémi Emonet"> |
11 | 11 | <meta name="venue" content="PWA M1 DSC"> |
12 | - <meta name="date" content="2016"> | |
12 | + <meta name="date" content="2017"> | |
13 | 13 | <meta name="affiliation" content="Université Jean Monnet − Laboratoire Hubert Curien"> |
14 | 14 | |
15 | 15 | <style type="text/css"> |
cours-04.html
View file @
9ac948f
1 | +<!DOCTYPE html> | |
2 | +<html> | |
3 | + <head> | |
4 | + <meta charset="utf-8"> | |
5 | + <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> | |
6 | + | |
7 | + <title>Programmation Web Avancée TP Basics Front</title> | |
8 | + <meta name="cours-n" content="3"> | |
9 | + | |
10 | + <meta name="author" content="Rémi Emonet"> | |
11 | + <meta name="venue" content="PWA M1 DSC"> | |
12 | + <meta name="date" content="2017"> | |
13 | + <meta name="affiliation" content="Université Jean Monnet − Laboratoire Hubert Curien"> | |
14 | + | |
15 | + <style type="text/css"> | |
16 | + li blockquote { | |
17 | + padding: 5px; | |
18 | + font-size: 20px; | |
19 | + } | |
20 | + blockquote { | |
21 | + border: 1px solid darkgrey; | |
22 | + border-radius: 5px; | |
23 | + padding: 0; | |
24 | + font-size: 30px; | |
25 | + font-style: italic; | |
26 | + } | |
27 | + blockquote p { | |
28 | + margin: 0; | |
29 | + padding: 30px; | |
30 | + } | |
31 | + blockquote p cite { | |
32 | + font-size: 20px; | |
33 | + } | |
34 | + </style> | |
35 | + | |
36 | + <!-- | |
37 | + <script src="deck.js/extensions/includedeck/load.js"></script> | |
38 | + <script src="extensions/slides-dev.js"></script> | |
39 | + --> | |
40 | + <script src="extensions/deck-packed.js"></script> | |
41 | + <script src="extensions/slides.js"></script> | |
42 | + <script>go()</script> | |
43 | + </head> | |
44 | + | |
45 | +<body> | |
46 | + | |
47 | +<div class="deck-container"> | |
48 | + | |
49 | + <div class="deck-loading-splash" style="background: black; color: chartreuse;"><span class="vcenter" style="font-size: 30px; font-family: Arial; ">Please wait, while our marmots are preparing the hot chocolate…</span></div> | |
50 | + | |
51 | +<section class="smart"> | |
52 | + | |
53 | +# @chunk: chunks/title.md | |
54 | + | |
55 | +# Questions ? <br/> Commentaires ? {no-print} | |
56 | + | |
57 | +# @chunk: chunks/objectives.md | |
58 | + | |
59 | +## Pour dès que possible (avant lundi) | |
60 | +- Projets !? {no-print} | |
61 | + - sujet | |
62 | + - description et mini cahier des charges | |
63 | + - quoi en Thymeleaf (génération coté serveur) ? | |
64 | + - quoi en Vue (génération coté client) ? | |
65 | + - groupes | |
66 | + - 3 personnes max | |
67 | + - nom et login github | |
68 | + - rappel | |
69 | + - soutenances : dernier créneau déjà planifié | |
70 | + - commencez tout de suite | |
71 | + | |
72 | +## Pour la prochaine fois | |
73 | +- Classe inversée | |
74 | + - autour du MVC etc | |
75 | + - comprendre ce qu'est une servlet | |
76 | + - avoir une idée de ce qu'est une annotation java | |
77 | + - lire au sujet de « Thymeleaf » | |
78 | + - lire au sujet de « dependency injection » | |
79 | + - ressources | |
80 | + - cours-03 | |
81 | + - cours-05 (à venir) | |
82 | + - wikipedia | |
83 | + - internet | |
84 | +- Dans tous les cas, finir le TP | |
85 | + | |
86 | +# Questions ? | |
87 | + | |
88 | +# TP 1 | |
89 | + | |
90 | +<!-- key points --> | |
91 | + | |
92 | +## Points Clés {key deck-status-fake-end} | |
93 | + | |
94 | +</section> | |
95 | + | |
96 | + <!-- deck.status snippet --> | |
97 | + <p class="deck-status deck-progress-10"> <span class="deck-status-current"></span> / <span class="deck-status-total"></span> − <span class="var-author">will be replaced by the author</span> − <span class="var-title">will be replaced by the title</span></p> | |
98 | + | |
99 | + <a data-progress-size=": spe.top(15, 555); height: 45*designRatio; left: slide.right - 90*designRatio; width: 90*designRatio" class="ccby" href="http://en.wikipedia.org/wiki/Creative_Commons_license" title="This work is under CC-BY licence." target="_blank"></a> | |
100 | + | |
101 | + <a class="ujm" data-progress-size=": spe.top(15, 525); height: 65*designRatio; left: slide.left; width: 130*designRatio" target="_blank"></a> | |
102 | + | |
103 | +</div> | |
104 | +<!-- clicky Cla --> | |
105 | +<script type="text/javascript"> | |
106 | +var clicky_site_ids = clicky_site_ids || []; | |
107 | +clicky_site_ids.push(100779706); | |
108 | +(function() { | |
109 | + var s = document.createElement('script'); | |
110 | + s.type = 'text/javascript'; | |
111 | + s.async = true; | |
112 | + s.src = '//static.getclicky.com/js'; | |
113 | + ( document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0] ).appendChild( s ); | |
114 | +})(); | |
115 | +</script> | |
116 | +<noscript><p><img alt="Clicky" width="1" height="1" src="//in.getclicky.com/100779706ns.gif" /></p></noscript> | |
117 | + | |
118 | + | |
119 | +<!-- Histats.com START (aync)--> | |
120 | +<script type="text/javascript">var _Hasync= _Hasync|| []; | |
121 | +_Hasync.push(['Histats.start', '1,2767123,4,0,0,0,00010000']); | |
122 | +_Hasync.push(['Histats.fasi', '1']); | |
123 | +_Hasync.push(['Histats.track_hits', '']); | |
124 | +(function() { | |
125 | +var hs = document.createElement('script'); hs.type = 'text/javascript'; hs.async = true; | |
126 | +hs.src = ('http://s10.histats.com/js15_as.js'); | |
127 | +(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(hs); | |
128 | +})();</script> | |
129 | +<noscript><a href="http://www.histats.com" target="_blank"><img src="http://sstatic1.histats.com/0.gif?2767123&101" alt="javascript hit counter" border="0"></a></noscript> | |
130 | +<!-- Histats.com END --> | |
131 | +</body> | |
132 | +</html> |
cours-05.html
View file @
9ac948f
1 | +<!DOCTYPE html> | |
2 | +<html> | |
3 | + <head> | |
4 | + <meta charset="utf-8"> | |
5 | + <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> | |
6 | + | |
7 | + <title>Programmation Web Avancée Spring MVC, Injection de Dépendances</title> | |
8 | + <meta name="cours-n" content="5"> | |
9 | + | |
10 | + <meta name="author" content="Rémi Emonet"> | |
11 | + <meta name="venue" content="PWA M1 DSC"> | |
12 | + <meta name="date" content="2017"> | |
13 | + <meta name="affiliation" content="Université Jean Monnet − Laboratoire Hubert Curien"> | |
14 | + | |
15 | + <style type="text/css"> | |
16 | + .slide.densish>ul {font-size: 70%;} | |
17 | + </style> | |
18 | + | |
19 | + <!-- | |
20 | + <script src="deck.js/extensions/includedeck/load.js"></script> | |
21 | + <script src="extensions/slides-dev.js"></script> | |
22 | + --> | |
23 | + <script src="extensions/deck-packed.js"></script> | |
24 | + <script src="extensions/slides.js"></script> | |
25 | + <script>go()</script> | |
26 | + </head> | |
27 | + | |
28 | +<body> | |
29 | + | |
30 | +<div class="deck-container"> | |
31 | + | |
32 | + <div class="deck-loading-splash" style="background: black; color: chartreuse;"><span class="vcenter" style="font-size: 30px; font-family: Arial; ">Please wait, while our marmots are preparing the hot chocolate…</span></div> | |
33 | + | |
34 | +<section class="smart"> | |
35 | + | |
36 | +# @chunk: chunks/title.md | |
37 | + | |
38 | +# Questions ? <br/> Commentaires ? {no-print} | |
39 | + | |
40 | +# @chunk: chunks/objectives.md | |
41 | + | |
42 | +## Programmation Web Avancée <span>{var-cours-n}</span> : Plan {#plan overview} | |
43 | +- MVC Web et Spring MVC {mvcweb} | |
44 | +- MVC Web en Pratique {mvcdemo} | |
45 | +- Injection de Dépendances {di} | |
46 | +- Introduction à la persistance en Java {persi} | |
47 | +- Java Persistence API (JPA) {jpa} | |
48 | +# @copy:#plan | |
49 | + | |
50 | + | |
51 | + | |
52 | + | |
53 | +<!-- MVC Web Spring (et un peu Java EE) --> | |
54 | +# @copy:#plan: %+class:inred: .mvcweb | |
55 | + | |
56 | +## MVC avec Spring dans ce cours {libyli} | |
57 | +- Modèle | |
58 | + - JavaBeans (objets Java) | |
59 | + - persistance avec JPA et Repositories de Spring Data | |
60 | +- Contrôleur | |
61 | + - description de route : annotations Java | |
62 | + - méthodes Java, avec injection de paramètres | |
63 | + - classe `Model` pour le ViewModel | |
64 | +- Vue | |
65 | + - templates Thymeleaf | |
66 | + - accès automatique au ViewModel | |
67 | + | |
68 | + | |
69 | +## Interaction Client Serveur et MVC | |
70 | +<p> </p> | |
71 | + | |
72 | +@svg: media/client-server-mvc/server-mvc.svg 700px 400px | |
73 | + | |
74 | +- @anim: #user, #client |#server |#r0 |#a0 |#s0,#router |#s1,#controller |#s2,#service |#s3,#db |#s4 |#s5,#view |#s6 |#s7 |#legend | |
75 | + | |
76 | + | |
77 | +<!-- ################################### --> | |
78 | +# @copy:#plan: %+class:inred: .mvcdemo | |
79 | + | |
80 | +## Quelques Éléments en Vrac (+ astuces) {libyli densish} | |
81 | +- Pour tester on peut faire un modèle en mémoire | |
82 | + - sous forme d'objets Java | |
83 | + - stockés dans une liste dans une variable « globale » | |
84 | +- Un/des contrôleur(s) {libyli} | |
85 | + - annotation de classe `@Controller` | |
86 | + - annotation de méthode `@RequestMapping(.....)` | |
87 | + - paramètre « magique » `Model m`, qui sera passé à la vue | |
88 | + - `m.addAttribute("letruc", valeur)` pour remplir le « modèle de vue » | |
89 | + - paramètre et annotation `@RequestParameter` pour les formulaires {unseen} | |
90 | + - capture de pattern dans l'url avec `@PathVariable` {unseen} | |
91 | +- Une/des vue(s) {libyli} | |
92 | + - fichiers Thymeleaf = XHTML + `th:....` (templates dite naturelles) | |
93 | + - remplacer le contenu d'une balise, attribut `... th:text="${letruc}"` | |
94 | + - ... | |
95 | + - accès à une propriété d'un objet `${letruc.machin}{}` équivalent à `letruc.getMachin()` en Java | |
96 | + - répéter la balise donnée, attribut `... th:each="e : ${letruc}"` | |
97 | + - mélanger texte et variables dans une balise | |
98 | + - la balise doit avoir `th:inline="text"` (ou il faut utiliser Thymeleaf 3) | |
99 | + - dans la balise, utiliser des doubles crochets, e.g., `Bonjour [[${nom}]] !` {unseen} | |
100 | + - gérer les formulaires (cf TP) avec `th:action`, `th:object`, `th:field` {unseen} | |
101 | +- Convention maven (système de build) + Spring | |
102 | + - fichiers Java dans `src/main/java/.....` | |
103 | + - fichiers templates dans `src/main/resources/templates/` | |
104 | + - fichiers statiques dans `src/main/resources/static/` (pour les .css, .js, images etc) | |
105 | + | |
106 | +# Start Démo | |
107 | + | |
108 | +# modèle simple et affichage de la liste | |
109 | + | |
110 | +# ajout "id" aux classe du modèle (pour la suppresison) | |
111 | + | |
112 | +# `th:inline="text"`, lien détails (`th:href="@{....}"`) | |
113 | + | |
114 | +# suppression, `@RequestParam`, `return "redirect:/....";` | |
115 | + | |
116 | +# page de détails `@PathVariable` | |
117 | + | |
118 | +# formulaire d'ajout avec `th:action` (et `th:object`, `th:field`, et constructeur vide) | |
119 | + | |
120 | +# End Démo | |
121 | + | |
122 | +<!-- ################################### --> | |
123 | +# @copy:#plan: %+class:inred: .di | |
124 | + | |
125 | +## Injection de dépendance (DI) {libyli} | |
126 | +- Cas sans injection de dépendance | |
127 | + - il nous faut une instance (par ex, une connection DB) | |
128 | + - on la crée (ou on utilise une « Factory ») | |
129 | +- Patron « injection de dépendance » | |
130 | + - Dependency Injection (DI) Inversion of Control (IoC) | |
131 | + - quelqu'un fourni l'instance (e.g. avec `@Component`), qui est injectée dans notre programme | |
132 | + - injection par constructeur ou par “setter” | |
133 | +```java | |
134 | +class UserObject { | |
135 | + @Inject Connection connection; | |
136 | + @Inject BlablaService blabla; | |
137 | +} | |
138 | +{slide denser} | |
139 | +``` | |
140 | +- Ce que fait à peu près le framework d'injection : il cherche des implémentations de Connection et BlablaService, puis | |
141 | +```java | |
142 | +Connection cDB = new SQLDataConnection(); | |
143 | +BlablaService s = new BlaBlaServiceImpl(); | |
144 | +UserObject obj = new UserObject(); | |
145 | +obj.setConnection(cDB); | |
146 | +obj.setService(s); | |
147 | +{slide denser} | |
148 | +``` | |
149 | + | |
150 | +# Injectons avec `@Inject` et `@Component` (+ ajout de dépendance maven à javax.inject) | |
151 | + | |
152 | + | |
153 | + | |
154 | + | |
155 | +<!-- ###################### --> | |
156 | +# @copy:#plan: %+class:inred: .persi | |
157 | + | |
158 | +## Persistence: motivation {libyli} | |
159 | +- When we close/restart an application | |
160 | + - memory is freed | |
161 | + - all objects are lost | |
162 | +- Persistence | |
163 | + - saving objects state | |
164 | + - ... on a permanent storage (non-volatile), e.g., database, file, etc | |
165 | + - allows for reloading objects later | |
166 | + | |
167 | +## Persistence Options in Java {libyli} | |
168 | +- Simple JDBC with or without DAOs (DataAccessObjects) | |
169 | + - direct access to the SQL database | |
170 | + - DAO: object that encapsulates/hides SQL requests | |
171 | +- ORM Concept: Object-Relational Mapping | |
172 | + - systematic mapping between Java objects and database relations/tables | |
173 | +- Persistence Frameworks with ORM | |
174 | + - JPA (Java Persistence API) // most recent | |
175 | + - JDO (Java Data Objects) // most complete (more than JPA) | |
176 | + - EJB 3 (Entreprise JavaBeans) // higher level | |
177 | + - Hibernate (Spring), via JPA // just a JPA backend now | |
178 | + | |
179 | + | |
180 | +## Simple JDBC Example | |
181 | +``` | |
182 | +import java.sql.*; | |
183 | +… | |
184 | +// JDBC driver name and database URL | |
185 | +static final String JDBC_DRIVER = "com.mysql.jdbc.Driver"; | |
186 | +static final String DB_URL = "jdbc:mysql://localhost/EMP"; | |
187 | +// Database credentials | |
188 | +static final String USER = "username"; | |
189 | +static final String PASS = "password"; | |
190 | + | |
191 | +public static void main(String[] args) throws ... { | |
192 | + | |
193 | + Class.forName(JDBC_DRIVER); | |
194 | + | |
195 | + Connection conn = DriverManager.getConnection(DB_URL, USER, PASS); | |
196 | + | |
197 | + Statement stmt = conn.createStatement(); | |
198 | + | |
199 | + ResultSet rs = stmt.executeQuery("SELECT id, prenom, nom, age FROM Employes"); | |
200 | + | |
201 | + while(rs.next()){ | |
202 | + | |
203 | + int id = rs.getInt("id"); | |
204 | + int age = rs.getInt("age"); | |
205 | + String first = rs.getString("prenom"); | |
206 | + String last = rs.getString("nom"); | |
207 | + | |
208 | + System.out.print(id + " : " + first + " " + last + " agé de " + age); | |
209 | + } | |
210 | + | |
211 | + rs.close(); // hum.... | |
212 | + stmt.close(); // hum.... | |
213 | + conn.close(); // hum.... | |
214 | +} | |
215 | +… | |
216 | +{denser} | |
217 | +``` | |
218 | +<div class="slide anim-show" data-dur="400" data-what="code>span:nth-of-type(-n+10)"></div> | |
219 | +<div class="slide anim-show" data-dur="400" data-what="code>span:nth-of-type(n+10):nth-of-type(-n+18)"></div> | |
220 | +<div class="slide anim-show" data-dur="400" data-what="code>span:nth-of-type(n+18):nth-of-type(-n+28)"></div> | |
221 | +<div class="slide anim-show" data-dur="400" data-what="code>span:nth-of-type(n+28):nth-of-type(-n+34)"></div> | |
222 | + | |
223 | +## Simple JDBC example, Java 7+ | |
224 | +```java | |
225 | +import java.sql.*; | |
226 | +… | |
227 | +// JDBC driver name and database URL | |
228 | +static final String JDBC_DRIVER = "com.mysql.jdbc.Driver"; | |
229 | +static final String DB_URL = "jdbc:mysql://localhost/EMP"; | |
230 | +// Database credentials | |
231 | +static final String USER = "username"; | |
232 | +static final String PASS = "password"; | |
233 | + | |
234 | +public static void main(String[] args) throws ... { | |
235 | + | |
236 | + Class.forName(JDBC_DRIVER); | |
237 | + | |
238 | + try ( | |
239 | + Connection conn = DriverManager.getConnection(DB_URL, USER, PASS); | |
240 | + Statement stmt = conn.createStatement(); | |
241 | + ResultSet rs = stmt.executeQuery("SELECT id, prenom, nom, age FROM Employes"); | |
242 | + ) { | |
243 | + | |
244 | + while(rs.next()){ | |
245 | + | |
246 | + int id = rs.getInt("id"); | |
247 | + int age = rs.getInt("age"); | |
248 | + String first = rs.getString("prenom"); | |
249 | + String last = rs.getString("nom"); | |
250 | + | |
251 | + System.out.print(id + " : " + first + " " + last + " agé de " + age); | |
252 | + } | |
253 | + } | |
254 | +} | |
255 | +{denser} | |
256 | +``` | |
257 | + | |
258 | +# JDBC simple : avantages/inconvénients ? | |
259 | + | |
260 | + | |
261 | +## Objet-Relational Mapping: concept | |
262 | + | |
263 | +- @anim: #objs |#rel |#car |#table |#arr0 |#arr1 |#arr2 |#arr3 |#arr4 | |
264 | +- @anim: #optionClass |#optionTable |#arr678 |#optColumn |#arr5 | |
265 | + | |
266 | +@SVG: media/orm.svg 800 420 | |
267 | + | |
268 | + | |
269 | + | |
270 | +## Object-Relational Mapping {libyli} | |
271 | +- Questions? | |
272 | + - what class corresponds to what table | |
273 | + - what attribute corresponds to what column | |
274 | + - what attribute corresponds to what foreign key | |
275 | + - what are the multiplicities | |
276 | +- In practice{libyli} | |
277 | + - using JDBC, manually… tedious | |
278 | + - source code very long (most of the app) // 30% | |
279 | + - very repetitive code | |
280 | + - dangerous code (error-prone) | |
281 | + - difficult to evolve | |
282 | + - using a persistence framework | |
283 | + - JPA, JDO, Hibernate | |
284 | + - writing metadata on Java classes and attributes | |
285 | + | |
286 | + | |
287 | +<!-- ###################### --> | |
288 | +# @copy:#plan: %+class:inred: .jpa | |
289 | + | |
290 | +## JPA: Java Persistance API {libyli} | |
291 | +- Why the JPA standard? {libyli} | |
292 | + - Pure JDBC: tedious | |
293 | + - Data Access Objects: abstraction, but too much code | |
294 | + - need a Object/Relational Mapping (ORM) description | |
295 | + - XML description too verbose and not DRY (Don't Repeat Yourself) | |
296 | + - proliferation of frameworks (hibernate, toplink, ...) | |
297 | + - need a usable standard | |
298 | +- What is JPA? | |
299 | + - a set of annotations and conventions // default values etc | |
300 | + - description of object/relational mappings | |
301 | + - originally, a part EJB 3 (Entreprise Java Beans) | |
302 | + - an `EntityManager` to manage data (transparent in Spring) | |
303 | + - to save, `em.persist()` | |
304 | + - to delete, `em.remove()` | |
305 | + - to read, `em.find()`, … | |
306 | + | |
307 | +## JPA Annotations: simple example | |
308 | +```java | |
309 | +import javax.persistence.Column; | |
310 | +import javax.persistence.Entity; | |
311 | +import javax.persistence.Id; | |
312 | +import javax.persistence.GeneratedValue; | |
313 | + | |
314 | + | |
315 | + | |
316 | +@Entity | |
317 | +public class Car { | |
318 | + | |
319 | + | |
320 | + @Id | |
321 | + @GeneratedValue(strategy = GenerationType.AUTO) | |
322 | + private long id; | |
323 | + | |
324 | + | |
325 | + private String company; | |
326 | + | |
327 | + | |
328 | + private String model; | |
329 | + | |
330 | + | |
331 | + private long price; | |
332 | + | |
333 | + ...constr/get/set... Important! | |
334 | +} | |
335 | + | |
336 | +... | |
337 | + | |
338 | +EntityManager em; | |
339 | +... | |
340 | +em.persist(myCar); | |
341 | +{} | |
342 | +``` | |
343 | + | |
344 | +## JPA Annotations: simple example | |
345 | +```java | |
346 | +import javax.persistence.Column; | |
347 | +import javax.persistence.Entity; | |
348 | +import javax.persistence.Id; | |
349 | +import javax.persistence.GeneratedValue; | |
350 | +import javax.persistence.Table; | |
351 | + | |
352 | +@Entity | |
353 | +@Table(name = "Vehicle") | |
354 | +public class Car { | |
355 | + | |
356 | + @Id | |
357 | + @Column(name = "id") | |
358 | + @GeneratedValue(strategy = GenerationType.AUTO) | |
359 | + private long id; | |
360 | + | |
361 | + @Column(name = "company") | |
362 | + private String company; | |
363 | + | |
364 | + @Column(name = "model") | |
365 | + private String model; | |
366 | + | |
367 | + @Column(name = "price") | |
368 | + private long price; | |
369 | + | |
370 | + ...constr/get/set... Important! | |
371 | +} | |
372 | + | |
373 | +... | |
374 | + | |
375 | +EntityManager em; | |
376 | +... | |
377 | +em.persist(myCar); | |
378 | +{} | |
379 | +``` | |
380 | + | |
381 | + | |
382 | +## JPA Annotations // make them write something | |
383 | +- Others {right autre} | |
384 | + - @PersistenceContext // expliquer qu'il faut sauver les EJB | |
385 | + - … | |
386 | +- Class-level | |
387 | + - @Entity | |
388 | + - @Table | |
389 | + - (EJB @Stateless) | |
390 | + - (EJB @Stateful) | |
391 | + - … | |
392 | +- Attribute-level, JavaBean relations {right relations} | |
393 | + - @OneToOne | |
394 | + - @ManyToOne | |
395 | + - @OneToMany | |
396 | + - @ManyToMany | |
397 | + - @MapKey | |
398 | + - @OrderBy | |
399 | + - … | |
400 | +- Attribute-level, JavaBean {attr} | |
401 | + - @Column | |
402 | + - @Id | |
403 | + - @GeneratedValue | |
404 | + - @Temporal, @Lob, @Basic | |
405 | + - @Version | |
406 | + - @Transient | |
407 | + - … | |
408 | + - @anim: .attr | .relations | .autre | |
409 | + | |
410 | +## Manipulating JPA Entities {libyli} | |
411 | +- (Using an `EntityManager`) | |
412 | + - to read, `em.find()`, … | |
413 | + - to save, `em.persist()` | |
414 | + - to delete, `em.remove()` | |
415 | +- Using `Repositories` | |
416 | + - abstraction to list and filter objects | |
417 | + - need to define an interface | |
418 | + - implemented automatically, e.g., by Spring Data | |
419 | + - interfaces: Repository, CrudRepository, PagingAndSortingRepository | |
420 | + - implementation is obtained via dependency injection | |
421 | + | |
422 | +# JPA (`@Entity`, `@Id`, `@OneToMany`, ...), Spring Data (`CrudRepository` x2 + `.save`), `/TEST` | |
423 | + | |
424 | +## What Did We Just Do? {libyli} | |
425 | +- Update the model | |
426 | + - add an `@Entity` on the class | |
427 | + - add a `long id` field, <br/> with `@Id @GeneratedValue(strategy=GenerationType.AUTO) {dense}` | |
428 | +- Create a new repository | |
429 | + - an (empty) interface (not a class) | |
430 | + - extending *CrudRepository<MyEntity, Long>{smartcode}* | |
431 | +- Used the new repository interface | |
432 | + - injected it | |
433 | + - used `findAll` and `save` | |
434 | + - the implementation being provided by spring data | |
435 | +- According to project configuration (and defaults) | |
436 | + - spring automatically uses an H2 database | |
437 | + - the database is in memory (by default) | |
438 | + - the database schema is automatically created | |
439 | + - the database is dropped at startup | |
440 | + | |
441 | +# Keeping Our Data! <br/> Tuning `application.properties{dense}` | |
442 | + | |
443 | +## What Did We Just Do? {libyli} | |
444 | +- Changing project configuration | |
445 | + - to override default configuration | |
446 | + - adding key=value properties in `application.properties` | |
447 | +- Using a file database (instead of solely in-memory) | |
448 | + - `spring.datasource.url=jdbc:h2:/tmp/mytestdb` | |
449 | +- Stopped dropping (and recreating) the database everytime | |
450 | + - `spring.jpa.hibernate.ddl-auto=none` | |
451 | +- NB about previous point | |
452 | + - in case one need to re-create the databse (schema update) | |
453 | + - the line can be remove | |
454 | + - or, use `spring.jpa.hibernate.ddl-auto=create-drop` | |
455 | +- Some properties | |
456 | + - `spring.datasource.password`, `spring.datasource.username` | |
457 | + - `server.port` | |
458 | + - and <a href="http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html" target="_blank">WAY more</a> | |
459 | + | |
460 | + | |
461 | +# ORM : avantages/inconvénients ? | |
462 | + | |
463 | + | |
464 | +</section> | |
465 | + | |
466 | + <!-- deck.status snippet --> | |
467 | + <p class="deck-status deck-progress-10"> <span class="deck-status-current"></span> / <span class="deck-status-total"></span> − <span class="var-author">will be replaced by the author</span> − <span class="var-title">will be replaced by the title</span></p> | |
468 | + | |
469 | + <a data-progress-size=": spe.top(15, 555); height: 45*designRatio; left: slide.right - 90*designRatio; width: 90*designRatio" class="ccby" href="http://en.wikipedia.org/wiki/Creative_Commons_license" title="This work is under CC-BY licence." target="_blank"></a> | |
470 | + | |
471 | + <a class="ujm" data-progress-size=": spe.top(15, 525); height: 65*designRatio; left: slide.left; width: 130*designRatio" target="_blank"></a> | |
472 | + | |
473 | +</div> | |
474 | +<!-- clicky Cla --> | |
475 | +<script type="text/javascript"> | |
476 | +var clicky_site_ids = clicky_site_ids || []; | |
477 | +clicky_site_ids.push(100779706); | |
478 | +(function() { | |
479 | + var s = document.createElement('script'); | |
480 | + s.type = 'text/javascript'; | |
481 | + s.async = true; | |
482 | + s.src = '//static.getclicky.com/js'; | |
483 | + ( document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0] ).appendChild( s ); | |
484 | +})(); | |
485 | +</script> | |
486 | +<noscript><p><img alt="Clicky" width="1" height="1" src="//in.getclicky.com/100779706ns.gif" /></p></noscript> | |
487 | + | |
488 | + | |
489 | +<!-- Histats.com START (aync)--> | |
490 | +<script type="text/javascript">var _Hasync= _Hasync|| []; | |
491 | +_Hasync.push(['Histats.start', '1,2767123,4,0,0,0,00010000']); | |
492 | +_Hasync.push(['Histats.fasi', '1']); | |
493 | +_Hasync.push(['Histats.track_hits', '']); | |
494 | +(function() { | |
495 | +var hs = document.createElement('script'); hs.type = 'text/javascript'; hs.async = true; | |
496 | +hs.src = ('http://s10.histats.com/js15_as.js'); | |
497 | +(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(hs); | |
498 | +})();</script> | |
499 | +<noscript><a href="http://www.histats.com" target="_blank"><img src="http://sstatic1.histats.com/0.gif?2767123&101" alt="javascript hit counter" border="0"></a></noscript> | |
500 | +<!-- Histats.com END --> | |
501 | +</body> | |
502 | +</html> |
index.html
View file @
9ac948f
... | ... | @@ -13,8 +13,8 @@ |
13 | 13 | body {display: inline-block;} |
14 | 14 | h1 {color: gray; margin-bottom: 2em;} |
15 | 15 | h2 {color: white; background: black; margin:0; margin-top: 120px;} |
16 | - a {display:inline-block; float: left; width: 165px; padding: 15px;} | |
17 | - a {margin-left: 6px;} | |
16 | + a {display:inline-block; width: 160px; padding: 15px; vertical-align: top; margin-left: 6px; text-align: center;} | |
17 | + body>div {text-align: left;} | |
18 | 18 | a:nth-child(4n+1) {margin-left:0;} |
19 | 19 | a {background: rgb(225, 73, 56); color: white; text-decoration: none; font-weight: bold;} |
20 | 20 | a.proj {min-height: 65px;} |
... | ... | @@ -33,7 +33,9 @@ |
33 | 33 | <a class="outlined" href="more-aide-transparents.html">Voir les slides?</a> |
34 | 34 | <a href="cours-01.html">Slides 1 <br/> introduction</a> |
35 | 35 | <a href="cours-02.html">Slides 2 <br/> HTML+CSS</a> |
36 | - <a href="cours-03.html" style="font-size:90%;">Slides 3 <br/> MVC, Spring+Thymeleaf</a> | |
36 | + <a href="cours-03.html" style="font-size:80%;">Slides 3 <br/> MVC, Spring+Thymeleaf</a> | |
37 | + <a href="cours-04.html">Slides 4 <br/> Projet, TP1</a> | |
38 | + <a href="cours-05.html">Slides 5 <br/> Thymeleaf, DI</a> | |
37 | 39 | |
38 | 40 | <h2>Code des séances</h2> |
39 | 41 | <a data-code-date="09-13"></a> |