List of commits:
Subject Hash Author Date (UTC)
Exercises fix, naming problems. 2b00c9f2306dd4d05f6919b4c06bc61b5786917f au 2018-12-21 02:10:54
Fixing some exercises. d5053a4b04b16b1817f2e8edb67f9ca7a6c48eb9 au 2018-12-21 01:24:09
Started to externalize the code, fixed the makefile, added a style for HTML files, fixed a lot of solution / problem / exercise environment, cleaned some fig code cfc0c26c5fb9ea64dfd101b9a1a70bc34dfa7082 au 2018-12-20 07:19:10
Re-organization of the structure and of the makefile. d352a7419a507c83374d78c8723d3aaebbaf1e0d au 2018-12-19 02:36:38
Pushing to merge. 92a45b2d1f200221602d730030f87f26e65e335d au 2018-12-19 01:13:42
Pushing to merge. d937aa46e12ee344113794dbb778eccb727819d3 au 2018-12-19 01:09:15
Fixing underline + solution environment. 4f207ab8ae51b1d87d0e83b7b813a91e30bf361f aubert@math.cnrs.fr 2018-12-18 20:03:10
Fixing underline + solution environment. 895823a4d392501285e613325078e9fce7bdd95b aubert@math.cnrs.fr 2018-12-18 20:02:55
Adding info. relative to website aee6744e0c80c31fdf3de459a3265db2211c8b9f aubert@math.cnrs.fr 2018-12-18 14:24:50
Finishing to externalize figures to external files. b7b49588bde465058c526454b938ac27b1447487 aubert@math.cnrs.fr 2018-12-17 20:01:54
Factorizing some aspect, separating fugires, re-wrote makefil, added treatment for html and odt outputs. 91d14fa349fe376408bcc48e4ada948777bda5a0 au 2018-12-17 02:57:14
Fixing project archeticture, tayloring README and moving typesetting section from lecture notes to README. c00c920db70a59ee8626134287aa47455fcb3e03 au 2018-12-16 19:51:52
Fine-tuning makefile 2ce6e9dea5235a97c02b97e548567ff4584c3153 au 2018-12-16 05:41:35
Fixing da441e5483d8153bff9b25f50230f584c4d67c5e au 2018-12-16 05:38:00
re-adding templates. bfe4f6aa774c7befef9eda07f31edb5c9907cedb au 2018-12-16 05:30:19
Restore er tex files. 771634fed59ac3a00fa3fa8ee292e98c4e35e3d6 au 2018-12-16 05:26:43
Changing vect. format from SVG to PDF. fa1276c21b6d139d52bd2c0405a9eb694e1a932d au 2018-12-16 05:25:50
Fixing minor typos 3fd56098f9022b48fadff8e3ea10fd7fcd49213a au 2018-12-16 04:05:47
Re-organization of the project. ccb3e4e35a17076f72b836720948ba7cfe86155b au 2018-12-16 03:16:19
Ending reporting notes on paper, added planned schedule, added meta-info and made tthe pdf TOC deeper. 96ffdff901b7e059471c34d7f7df6771ded38783 aubert@math.cnrs.fr 2018-05-30 15:46:13
Commit 2b00c9f2306dd4d05f6919b4c06bc61b5786917f - Exercises fix, naming problems.
Author: au
Author date (UTC): 2018-12-21 02:10
Committer name: au
Committer date (UTC): 2018-12-21 02:10
Parent(s): d5053a4b04b16b1817f2e8edb67f9ca7a6c48eb9
Signer:
Signing key:
Signing status: N
Tree: c2526d1c0096e8f5055f29b8b7a3261e183bf5c5
File Lines added Lines deleted
notes/code/java/AdvancedProg.java 248 0
notes/code/java/ProgWithErrors.java 38 0
notes/lectures_notes.md 116 413
File notes/code/java/AdvancedProg.java added (mode: 100644) (index 0000000..af8273a)
1 /* code/java/AdvancedProg.sql */
2
3 /*
4
5 This is a long program, introducing:
6 I. How to pass options when connecting to the database,
7 II. How to create a table
8 III. How to insert values
9 IV. How to use prepared statements
10 V. How to read backward and write in ResultSets
11
12 If you want to run this program multiple times, you have to either:
13
14 1. Comment first statement of II. Creating a table
15 2. Change the name of the schema, from HW_DBPROG to whatever you want
16 3. Drop the DVD table: connect to your database, and then enter
17 USE HW_DBPROG;
18 DROP TABLE DVD;
19 Or do it from within your program!
20
21 If you use option 1, you will keep inserting tuples in your table: cleaning it with
22 DELETE FROM DVD;
23 can help. You can do it from within the program!
24 */
25
26 import java.sql.*;
27
28 public class AdvancedProg {
29 public static void main(String[] args) {
30 try (
31
32 /*
33 * I. Passing options to the dababse
34 */
35
36 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/HW_DBPROG"
37 + "?user=testuser"
38 + "&password=password"
39 + "&allowMultiQueries=true"
40 + "&createDatabaseIfNotExist=true"
41 + "&useSSL=true");
42
43 // Read about other options at
44 // https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-configuration-properties.html
45 // https://jdbc.postgresql.org/documentation/head/connect.html
46
47 Statement stmt = conn.createStatement();
48 ) {
49
50 /*
51 * II. Creating a table
52 */
53
54 stmt.execute("CREATE TABLE DVD (" +
55 "Title CHAR(25) PRIMARY KEY, " +
56 "Minutes INTEGER, " +
57 "Price DOUBLE)");
58
59 /* If we were to execute
60 * SHOW TABLES
61 * directly in the MySQL interpreter, this would display at the screen
62 *
63 * +--------------------------+
64 * | Tables_in_HW_NewDataBase |
65 * +--------------------------+
66 * | DVD |
67 * +--------------------------+
68 *
69 * But here, to access this information, we will use the connection's metadata.
70 */
71
72 DatabaseMetaData md = conn.getMetaData();
73 // DatabaseMetaData is a class used to get information about the database: the driver, the user, the versions, etc.
74
75 ResultSet rs = md.getTables(null, null, "%", null);
76
77 /*
78 * You can read at
79 * https://docs.oracle.com/javase/7/docs/api/java/sql/DatabaseMetaData.html#getTables(java.lang.String,%20java.lang.String,%20java.lang.String,%20java.lang.String[])
80 * the full specification of this method.
81 * All you need to know, for now, is that the third parameter is
82 * String tableNamePattern,
83 * i.e., what must match the table name as it is stored in the database
84 * Here, by using the wildcard "%", we select all the table names.
85 * We can then iterate over the ResultSet as usual:
86 */
87
88 while (rs.next()) {
89 System.out.println(rs.getString(3)); // In the ResultSet returned by getTables, 3 is the TABLE_NAME.
90 }
91
92 /*
93 * III. Inserting values
94 */
95
96 String sqlStatement = "INSERT INTO DVD VALUES ('Gone With The Wind', 221, 3);";
97 int rowsAffected = stmt.executeUpdate(sqlStatement);
98 System.out.print(sqlStatement + " changed " + rowsAffected + " row(s).\n");
99
100
101 /*
102 * Batch Insertion
103 */
104
105 String insert1 = "INSERT INTO DVD VALUES ('Aa', 129, 0.2)";
106 String insert2 = "INSERT INTO DVD VALUES ('Bb', 129, 0.2)";
107 String insert3 = "INSERT INTO DVD VALUES ('Cc', 129, 0.2)";
108 String insert4 = "INSERT INTO DVD VALUES ('DD', 129, 0.2)";
109
110 // Method 1: Using executeUpdate, if the option allowMultiQueries=true was passed in the url given to getConnection and your DBMS supports it.
111 stmt.executeUpdate(insert1 + ";" + insert2);
112
113 // Method 2: Using the addBatch and executeBatch methods
114 stmt.addBatch(insert3);
115 stmt.addBatch(insert4);
116 stmt.executeBatch();
117
118
119 /*
120 * IV. Prepared Statements
121 */
122
123 // Example 1
124 sqlStatement = "SELECT title FROM DVD WHERE Price <= ?"; // We have a string with an empty slot, represented by "?".
125 PreparedStatement ps = conn.prepareStatement(sqlStatement); // We create a PreparedStatement object, using that string with an empty slot.
126 float maxprice = 0.5f;
127 ps.setFloat(1, maxprice); // This statement says "Fill the first slot with the value of maxprice".
128 ResultSet result = ps.executeQuery(); // And then we can execute the query, and display the results:
129
130 System.out.printf("For %.2f you can get:\n", maxprice);
131
132 while(result.next()){
133 System.out.printf("\t %s \n", result.getString(1));
134 }
135
136 // Example 2
137 sqlStatement = "INSERT INTO DVD VALUES (?, ?, ?)"; // Now, our string has 3 empty slots, and it is an INSERT statement.
138 PreparedStatement preparedStatement = conn.prepareStatement(sqlStatement);
139
140 preparedStatement.setString(1, "The Great Dictator");
141 preparedStatement.setInt(2, 124);
142 preparedStatement.setFloat(3, 5.4f);
143
144 rowsAffected = preparedStatement.executeUpdate(); // You can check "by hand" that this statement was correctly executed.
145 System.out.print(preparedStatement.toString() + " changed "+ rowsAffected + " row(s).\n");
146
147
148 // If we try to mess things up, i.e., provide wrong datatypes:
149 preparedStatement.setString(1, "The Great Dictator");
150 preparedStatement.setString(2, "The Great Dictator");
151 preparedStatement.setString(3, "The Great Dictator");
152
153 // Java compiler will be ok, but we'll have an error at execution time when executing the query. You can uncomment the line below to see for yourself.
154 //rowsAffected = preparedStatement.executeUpdate();
155
156 // Of course, we can use prepared statement inside loops.
157 for (int i = 1; i < 5; i++) {
158 preparedStatement.setString(1, "Saw " + i);
159 preparedStatement.setInt(2, 100);
160 preparedStatement.setFloat(3, .5f);
161 preparedStatement.executeUpdate();
162 }
163
164 /*
165 * V. Reading backward and writing in ResultSets
166 */
167
168 // To read backward and write in ResultSets, you need to have a statement with certain options:
169
170 Statement stmtNew = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
171
172 /*
173 * Those options change two things about the ResultSet we obtain using this statement
174 *
175 * The first argument is the scrolling level:
176 * TYPE_FORWARD_ONLY = default.
177 * TYPE_SCROLL_INSENSITIVE = can scroll, but updates don't impact result set.
178 * TYPE_SCROLL_SENSITIVE = can scroll, update impact result set.
179 *
180 * The second argument is the concurrency level:
181 * CONCUR_READ_ONLY: default.
182 * CONCUR_UPDATABLE: we can change the database without issuing SQL statement.
183 */
184
185 /*
186 * Reading backward
187 */
188
189 sqlStatement = "SELECT title FROM DVD WHERE Price < 1;";
190 result = stmtNew.executeQuery(sqlStatement);
191
192 System.out.println("For $1, you can get:");
193
194 if (result.last()) { // We can jump to the end of the ResultSet
195 System.out.print(result.getString("Title") + " ");
196 }
197
198 System.out.print("and also, (in reverse order)");
199
200 while (result.previous()) { // Now we can scroll back!
201 System.out.print(result.getString("Title") + " ");
202 }
203
204 /*
205 * Other methods to navigate in ResultSet:
206 * first()
207 * last()
208 * next()
209 * previous()
210 * relative(x) : move cursor x times (positive = forward, negative = backward)
211 * absolute(x): move to the row number x. 1 is the first.
212 */
213
214 /*
215 * Changing the values
216 */
217
218 System.out.print("\n\nLet us apply a 50% discount. Currently, the prices are:\n");
219
220 sqlStatement = "SELECT title, price FROM DVD;";
221 result = stmtNew.executeQuery(sqlStatement);
222 while (result.next()) {
223 System.out.printf("%20s \t $%3.2f\n", result.getString("title") , result.getDouble("price"));
224 }
225
226
227 result.absolute(0); // We need to scroll back!
228
229 while (result.next()) {
230 double current = result.getDouble("price");
231 result.updateDouble("price", (current * 0.5));
232 result.updateRow();
233 }
234 System.out.print("\n\nAfter update, the prices are:\n");
235
236 result.absolute(0); // We need to scroll back!
237
238 while (result.next()) {
239 System.out.printf("%20s \t $%3.2f\n", result.getString("title") , result.getDouble("price"));
240 }
241
242
243 conn.close();
244 } catch (SQLException ex) {
245 ex.printStackTrace();
246 }
247 }
248 }
File notes/code/java/ProgWithErrors.java added (mode: 100644) (index 0000000..f4a5489)
1 /* code/java/ProgWithErrors.java */
2
3 import java.sql.*;
4
5 public class ProgWithErrors{
6 public static void main(String[] args) {
7 try (
8 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/"
9 +"HW_TestDB?user=testuser&password=password");
10 Statement stmt = conn.createStatement();
11 ) {
12
13 /* Errors after this point.*/
14
15 String strSelect = "SELECT title FROM DISKS WHERE qty > 40;";
16 ResultSet rset = stmt.executeUpdate(strSelect);
17
18 System.out.println("The records selected are: (listed last first):");
19 rset.last();
20
21 while(rset.previous()) {
22 String title = rset.getDouble("title");
23 System.out.println(title + "\n");
24 }
25
26 String sss = "SELECT title FROM DISKS WHERE Price <= ?";
27 PreparedStatement ps = conn.prepareStatement(sss);
28 ResultSet result = ps.executeQuery();
29
30 conn.close();
31
32 /* Errors before this point.*/
33
34 } catch(SQLException ex) {
35 ex.printStackTrace();
36 }
37 }
38 }
File notes/lectures_notes.md changed (mode: 100644) (index 5b31f3e..6153e9e)
... ... How things can go wrong:
586 586 How things can go wrong: How things can go wrong:
587 587
588 588 - Deleting tuples inadvertently (meta) - Deleting tuples inadvertently (meta)
589 - Delecing tuples that are referenced (a., b., c.)
589 - Delecing tuples that are referenced (1., 2., 3.)
590 590
591 591 #### Update (a.k.a. modify) #### Update (a.k.a. modify)
592 592
 
... ... How things can go wrong:
596 596
597 597 - Duplicate value for the primary key (1.) - Duplicate value for the primary key (1.)
598 598 - `NULL` for the primary key (1.) - `NULL` for the primary key (1.)
599 - Change value that are referenced (a., b., c.)
599 - Change value that are referenced (1., 2., 3.)
600 600 - Change foreign key to a non-existing value (1.) - Change foreign key to a non-existing value (1.)
601 601
602 602
 
... ... There are 14 different types of diagrams, divided between two categories: struct
3831 3831
3832 3832 ![](img/UML_Diagrammhierarchie.svg) ![](img/UML_Diagrammhierarchie.svg)
3833 3833
3834 (Source: <https://commons.wikimedia.org/wiki/File:UML_diagrams_overview.svg>)
3835
3834 3836 #### Structural UML diagrams #### Structural UML diagrams
3835 3837
3836 3838 They describe structural, or static, relationships between objects, softwares. They describe structural, or static, relationships between objects, softwares.
 
... ... Solution +.#
4206 4208 : For a weak entity attribute, it is the attribute that can uniquely identify weak entites that are related to the same owner entity. : For a weak entity attribute, it is the attribute that can uniquely identify weak entites that are related to the same owner entity.
4207 4209
4208 4210 Solution +.# Solution +.#
4211 ~
4209 4212
4210 4213 Entity 1 | Cardinality Ratio | Entity 2 | Explanation | Entity 1 | Cardinality Ratio | Entity 2 | Explanation |
4211 4214 | --- | :---: | --- | --------| | --- | :---: | --- | --------|
 
... ... Problem (Design for your Professor) +.#designforprof
4368 4371 ~ ~
4369 4372 Your professor designed the following relational model at some point in his career, to help him organizing his exams and the students grades: Your professor designed the following relational model at some point in his career, to help him organizing his exams and the students grades:
4370 4373
4374 <!-- bug with table -->
4371 4375 Table Name and Attributes | Example of Value | Table Name and Attributes | Example of Value |
4372 4376 --- | --- --- | ---
4373 4377 EXAM(Number, Date, Course) | < 1, '2018-02-14', 'CSCI3410'> EXAM(Number, Date, Course) | < 1, '2018-02-14', 'CSCI3410'>
4374 4378 PROBLEM(Statement, Points, Length, Exam) | < 'Your professor designed…', 10, '00:10:00', 1> PROBLEM(Statement, Points, Length, Exam) | < 'Your professor designed…', 10, '00:10:00', 1>
4375 4379 STUDENT\_GRADE(Login, Exam, Grade) | < 'aalyx', 1, 83> STUDENT\_GRADE(Login, Exam, Grade) | < 'aalyx', 1, 83>
4376 4380
4377 where `EXAM.Number`, `PROBLEM.Statement`, `STUDENT_GRADE.Login` and `STUDENT_GRADE.Exam` are primary key, and where `STUDENT_GRADE.Exam` and `PROBLEM.Exam` both refer to `EXAM.Number`.
4381 where `EXAM.Number`, `PROBLEM.Statement`, `STUDENT_GRADE.Login` and `STUDENT_GRADE.Exam` are primary key, and where `STUDENT_GRADE.Exam` and `PROBLEM.Exam` both refer to `EXAM.Number`.
4378 4382
4379 The idea was to have
4383 The idea was to have
4380 4384
4381 - The `EXAM` table storing information about exams,
4382 - One entry per problem in the PROBLEM table, and to associate every problem to an exam,
4383 - The grade of one student for one particular exam stored in the `STUDENT\_GRADE` table.
4384
4385 Unfortunately, this design turned out to be terrible.
4386 Describe at least one common and interesting situation where this model would fail to fulfill its purpose, and propose a way to correct the particular problem you identified.
4387
4388 <!-- Bug with table -->
4385 - The `EXAM` table storing information about exams,
4386 - One entry per problem in the PROBLEM table, and to associate every problem to an exam,
4387 - The grade of one student for one particular exam stored in the `STUDENT\_GRADE` table.
4389 4388
4389 Unfortunately, this design turned out to be terrible.
4390 Describe at least one common and interesting situation where this model would fail to fulfill its purpose, and propose a way to correct the particular problem you identified.
4390 4391
4391 4392 --- ---
4392 4393
 
... ... Problem (ER diagram for Car Insurance) +.#car-insurance
4434 4435
4435 4436 --- ---
4436 4437
4437 Problem +.#ERtoREL
4438 ~ \
4438 Problem (ER-to-Relation mapping for Car Insurance) +.#ERtoREL
4439 ~
4439 4440
4440 4441 Apply the ER-to-Relation mapping to your ER diagram from the previous problem. Apply the ER-to-Relation mapping to your ER diagram from the previous problem.
4441 4442
4442 4443 --- ---
4443 4444
4444 Problem +.#
4445 ~ \
4445 Problem (ER-to-Relation mapping for Country)+ .#
4446 ~
4446 4447
4447 Consider the following E.R. schema:
4448 Consider the following E.R. schema:
4448 4449
4449 ![](fig/er/Country)
4450 \
4450 ![](fig/er/Country)
4451 \
4451 4452
4452 where
4453 where
4453 4454
4454 - "W\_IN" stands for "WRITTEN\_IN", and
4455 - "B\_W\_F" stands for "BORROWS\_WORDS\_FROM".
4455 - "W\_IN" stands for "WRITTEN\_IN", and
4456 - "B\_W\_F" stands for "BORROWS\_WORDS\_FROM".
4456 4457
4457 For this relationship, on the left-hand side is the language that borrows a word, and on the right-hand side is the language that provides the loanword.
4458 For this relationship, on the left-hand side is the language that borrows a word, and on the right-hand side is the language that provides the loanword.
4458 4459
4459 Map that E.R. diagram to a relational database schema.
4460 Map that E.R. diagram to a relational database schema.
4460 4461
4461 4462 --- ---
4462 4463
 
... ... Based on the given primary key, is this relation in 1NF, 2NF, or 3NF? Why or why
4480 4481
4481 4482 --- ---
4482 4483
4483 Problem +.#
4484 Problem (Normalizing the FLIGHT relation) +.#
4484 4485 ~ ~
4485 4486
4486 4487 Consider the following relation: Consider the following relation:
 
... ... Problem +.#
4499 4500
4500 4501 --- ---
4501 4502
4502 Problem +.#bike
4503 Problem (From business statement to dependencies) +.#bike
4503 4504 ~ ~
4504 4505
4505 4506 This problem asks you to convert business statements into dependencies. This problem asks you to convert business statements into dependencies.
 
... ... Problem +.#bike
4523 4524
4524 4525 --- ---
4525 4526
4526 Problem +.#
4527 Problem (Normalization)+.#
4527 4528 ~ ~
4528 4529
4529 4530 <!-- bug with table --> <!-- bug with table -->
4530
4531 4531 Consider the relations $R$ and $T$ below, and their functional dependencies (on top of the one induced by the primary keys): Consider the relations $R$ and $T$ below, and their functional dependencies (on top of the one induced by the primary keys):
4532 4532
4533 4533 | |
 
... ... import java.sql.*;
4908 4908 public class FirstProg { public class FirstProg {
4909 4909 public static void main(String[] args) { public static void main(String[] args) {
4910 4910 try ( try (
4911 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/HW_ebookshop", "testuser","password");
4911 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/HW_EBOOKSHOP", "testuser","password");
4912 4912 Statement stmt = conn.createStatement(); Statement stmt = conn.createStatement();
4913 4913 ) { ) {
4914 4914 String strSelect = "SELECT title, price, qty FROM books WHERE qty > 40"; String strSelect = "SELECT title, price, qty FROM books WHERE qty > 40";
 
... ... public class FirstProg {
4942 4942 A couple of comments: A couple of comments:
4943 4943
4944 4944 - `java.sql.*` contains the classes `Connection`, `Statement`, `ResultSet`, `ResultSetMetadata`. - `java.sql.*` contains the classes `Connection`, `Statement`, `ResultSet`, `ResultSetMetadata`.
4945 - In the string `"jdbc:mysql://localhost:3306/HW_ebookshop"`, `jdbc` is the protocol, `mysql` is the subprotocol, `localhost` is the url of the database, `3306` is the port, and `HW_ebookshop` is the schema (that needs to already exist in this case).
4945 - In the string `"jdbc:mysql://localhost:3306/HW_EBOOKSHOP"`, `jdbc` is the protocol, `mysql` is the subprotocol, `localhost` is the url of the database, `3306` is the port, and `HW_EBOOKSHOP` is the schema (that needs to already exist in this case).
4946 4946 - Note that `strSelect` doesn't end with `;` (it could, but doesn't have to). - Note that `strSelect` doesn't end with `;` (it could, but doesn't have to).
4947 4947 - `next()` returns true if there is something left in the set of result, and move to the next line if it is the case. It is close to the code we would use to read from a file. - `next()` returns true if there is something left in the set of result, and move to the next line if it is the case. It is close to the code we would use to read from a file.
4948 4948 - We could use `1`, `2`, and `3` instead of `"title"`, `"price"` and `"qty"` in the `while` loop: `getString`, `getDouble` and `getInt` also take integers, corresponding to the position of the attribute in the result set. - We could use `1`, `2`, and `3` instead of `"title"`, `"price"` and `"qty"` in the `while` loop: `getString`, `getDouble` and `getInt` also take integers, corresponding to the position of the attribute in the result set.
 
... ... A couple of comments:
4950 4950
4951 4951 ### The database ### The database
4952 4952
4953 ~~~{.sqlmysql .numberLines}
4954 CREATE DATABASE HW_ebookshop;
4955
4956 USE HW_ebookshop;
4957
4958 CREATE TABLE books (
4959 id int PRIMARY KEY,
4960 title varchar(50),
4961 author varchar(50),
4962 price float,
4963 qty int
4964 );
4965
4966 INSERT INTO books VALUES (1001, 'Java for dummies', 'Tan Ah Teck', 11.11, 11);
4967 INSERT INTO books VALUES (1002, 'More Java for dummies', 'Tan Ah Teck', 22.22, 22);
4968 INSERT INTO books VALUES (1003, 'More Java for more dummies', 'Mohammad Ali', 33.33, 33);
4969 INSERT INTO books VALUES (1004, 'A Cup of Java', 'Kumar', 44.44, 44);
4970 INSERT INTO books VALUES (1005, 'A Teaspoon of Java', 'Kevin Jones', 55.55, 55);
4971 ~~~
4953 ```{.sqlmysql .numberLines include=code/sql/HW_EBOOKSHOP.sql}
4954 ```
4972 4955
4973 4956
4974 4957 ~~~{.plain .numberlines} ~~~{.plain .numberlines}
4975 MariaDB [HW_ebookshop]> SELECT * FROM books;
4958 MariaDB [HW_EBOOKSHOP]> SELECT * FROM books;
4976 4959 +------+----------------------------+--------------+-------+------+ +------+----------------------------+--------------+-------+------+
4977 4960 | id | title | author | price | qty | | id | title | author | price | qty |
4978 4961 +------+----------------------------+--------------+-------+------+ +------+----------------------------+--------------+-------+------+
 
... ... conn.close();
5035 5018
5036 5019 You would obtain: You would obtain:
5037 5020
5038 ~~~{.plain .numberLines}}
5021 ~~~{.plain .numberLines}
5039 5022 The records selected are: The records selected are:
5040 5023 1001 id, Java for dummies title, Tan Ah Teck author, 11.11 price, 11 qty 1001 id, Java for dummies title, Tan Ah Teck author, 11.11 price, 11 qty
5041 5024 1002 id, More Java for dummies title, Tan Ah Teck author, 22.22 price, 22 qty 1002 id, More Java for dummies title, Tan Ah Teck author, 22.22 price, 22 qty
 
... ... You can pass options when creating Statement objects to be able to read it both
5128 5111 ## Exercises {-} ## Exercises {-}
5129 5112
5130 5113 Exercise +.# Exercise +.#
5131 ~ What are the technologies that makes it possible for a Java application to communicate with a DBMS?
5132 5114
5133 Exercise +.#
5134 ~ What JDBC method do you call to get a connection to a database?
5115 : What are the technologies that makes it possible for a Java application to communicate with a DBMS?
5135 5116
5136 5117 Exercise +.# Exercise +.#
5137 ~ Briefly explain what the `next()` method from the `ResultSet` class does, and give its return type.
5138 5118
5139 Exercise +.#
5140 ~ How do you submit a `SELECT` statement to the DBMS?
5119 : What JDBC method do you call to get a connection to a database?
5141 5120
5142 5121 Exercise +.# Exercise +.#
5143 ~ Where is a `ResultSet` object's cursor initially pointing? How do you move the cursor forward in the result set?
5144 5122
5145 Exercise +.#
5146 ~ Give three navigation methods provided by `ResultSet`.
5123 : Briefly explain what the `next()` method from the `ResultSet` class does, and give its return type.
5147 5124
5148 5125 Exercise +.# Exercise +.#
5149 ~ Explain this JDBC URL format:
5150 5126
5151 ~~~{.java .numberLines}
5152 jdbc:mysql://localhost:3306/HW_NewDB?createDatabaseIfNotExist=true&useSSL=true
5153 ~~~
5127 : How do you submit a `SELECT` statement to the DBMS?
5154 5128
5155 5129 Exercise +.# Exercise +.#
5156 ~ In what class is the `getColumnName` method?
5157 5130
5158 Exercise +.#
5159 ~ What is a prepared statement?
5131 : Where is a `ResultSet` object's cursor initially pointing? How do you move the cursor forward in the result set?
5160 5132
5161 5133 Exercise +.# Exercise +.#
5162 ~ In the code below, there are five errors between line 11 and line 30. They are *not* subtle Java errors (like misspelling a key word) and do not come from the DBMS (so you should assume that the password is correct, that the database exists, etc.). For each error, highlight it precisely and give a short explanation.
5163 5134
5164 ~~~{.java .numberLines}
5165 import java.sql.*;
5135 : Give three navigation methods provided by `ResultSet`.
5166 5136
5167 public class MyProg{
5168 public static void main(String[] args) {
5169 try (
5170 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/"
5171 +"HW_TestDB?user=testuser&password=password");
5172 Statement stmt = conn.createStatement();
5173 ) {
5137 Exercise +.#
5138 ~
5174 5139
5175 /* Errors after this point.*/
5140 Explain this JDBC URL format:
5176 5141
5177 String strSelect = "SELECT title FROM disks WHERE qty > 40;";
5178 ResultSet rset = stmt.executeUpdate(strSelect);
5142 ~~~{.java .numberLines}
5143 jdbc:mysql://localhost:3306/HW_NewDB?createDatabaseIfNotExist=true&useSSL=true
5144 ~~~
5179 5145
5180 System.out.println("The records selected are: (listed last first):");
5181 rset.last();
5146 Exercise +.#
5182 5147
5183 while(rset.previous()) {
5184 String title = rset.getDouble("title");
5185 System.out.println(title + "\n");
5186 }
5148 : In what class is the `getColumnName` method?
5187 5149
5188 String sss = "SELECT title FROM disks WHERE Price <= ?";
5189 PreparedStatement ps = conn.prepareStatement(sss);
5190 ResultSet result = ps.executeQuery();
5150 Exercise +.#
5191 5151
5192 conn.close();
5152 : What is a prepared statement?
5193 5153
5194 /* Errors before this point.*/
5154 Exercise +.#
5155 ~
5195 5156
5196 } catch(SQLException ex) {
5197 ex.printStackTrace();
5198 }
5199 }
5200 }
5201 ~~~
5157 In the code below, there are five errors between line 13 and line 32.
5158 They are *not* subtle Java errors (like misspelling a key word) and do not come from the DBMS (so you should assume that the password is correct, that the database exists, etc.).
5159 For each error, highlight it precisely and give a short explanation.
5160
5161 ```{.java .numberLines include=code/java/ProgWithErrors.java}
5162 ```
5202 5163
5203 5164 Exercise +.# Exercise +.#
5204 ~ Write a small program that determine whenever the `null` value from Java is equal to the `NULL` value in your DBMS.
5165
5166 : Write a small program that determine whenever the `null` value from Java is equal to the `NULL` value in your DBMS.
5205 5167
5206 5168 ## Solution to Exercises {-} ## Solution to Exercises {-}
5207 5169
 
... ... Solution +.#
5245 5207 Solution +.# Solution +.#
5246 5208
5247 5209 : List errors in program TO DO. : List errors in program TO DO.
5248
5249 5210 <!-- <!--
5250 5211 % %
5251 5212 %METADATA %METADATA
 
... ... Solution +.#
5302 5263 ## Problems ## Problems
5303 5264
5304 5265 - If you experience troubles, <https://www.ntu.edu.sg/home/ehchua/programming/howto/ErrorMessages.html#JDBCErrors> might be a good read. - If you experience troubles, <https://www.ntu.edu.sg/home/ehchua/programming/howto/ErrorMessages.html#JDBCErrors> might be a good read.
5305 - [@Textbook6, 13.3.2] is a condensed, but good read. Many textbook on Java includes a part on Databases, cf. for instance the [Gaddis2014, Chapter 16].
5266 - [@Textbook6, 13.3.2] is a condensed, but good read. Many textbook on Java includes a part on Databases, cf. for instance [Gaddis2014, Chapter 16].
5306 5267
5307 5268
5308 Problem +.#
5309 ~ \
5310
5311 In the archive, navigate to `code/sql/`, open and read `HW\_ebookshop.sql`.
5312
5313 Then, open a terminal (or command-line interpreter), navigate to the folder where you stored that file (using `cd`), and type
5314
5315 ~~~{.bash}
5316 mysql -u testuser -p < HW_ebookshop.sql
5317 ~~~
5318
5319 for linux, or (something like)
5320
5321 ~~~{.bash}
5322 "C:\Program Files\MySQL\MySQL Server 5.7\bin\mysql.exe" -u testuser -p < HW_ebookshop.sql
5323 ~~~
5324
5325 for Windows.
5326
5327 You just discovered MySQL's batch mode, that perform *series* of instructions from a file.
5328 You can easily make sure that the database and the table were indeed created, and the values inserted.
5329
5330 ---
5331
5332 Problem +.#
5333 ~ \
5269 Problem (MySQL's batch mode and HW_EBOOKSHOP.sql) +.#mysql_batch
5270 ~
5334 5271
5335 This exercise supposes you successfully completed Problem~ \ref{qu:batch}.
5336 We will compile and execute your first database application, using Java and MySQL.
5337
5338 - I will assume that you have MySQL installed and set-up as indicated in Homeworks \#1 and \#2.
5339 - I will assume that you have Java installed. If not, please refer to <http://spots.augusta.edu/caubert/teaching/general/java/> for a simple program and the instructions to compile and execute it.
5340 - We need to set up the *driver* (or *connector*) to make the java `sql` API and MySQL communicate. To do so,
5341 \begin{- ize}
5342 - Go to <https://dev.mysql.com/downloads/connector/j/>
5343 - Click on "Download" in front of "Platform Independent (Architecture Independent), ZIP Archive"
5344 - Look for the (somewhat hidden) "No thanks, just start my download."
5345 - You will download a file named "mysql-connector-java-***.zip", where `***` is the version number.
5346 - Upon completion of the download, unzip the file, and locate the "mysql-connector-java-***-bin.jar" file.
5347 - Copy that file in `code/java/`.
5348 \end{- ize}
5349 - Open a terminal in that same folder, and compile `FirstProg.java`, using
5272 In the archive, navigate to `code/sql/` and open `HW_EBOOKSHOP.sql`.
5273 Then, open a terminal (or command-line interpreter), navigate to the folder where you stored that file (using `cd`), and type
5350 5274
5351 5275 ~~~{.bash} ~~~{.bash}
5352 javac FirstProg.java
5276 mysql -u testuser -p < HW_EBOOKSHOP.sql
5353 5277 ~~~ ~~~
5354 5278
5355 (or an equivalent command for windows).
5356 Normally, nothing will be printed, but a `FirstProg.class` file will be created.
5357 - Now, execute that program, using
5279 for linux, or (something like)
5358 5280
5359 5281 ~~~{.bash} ~~~{.bash}
5360 java -cp .:mysql-connector-java-***-bin.jar FirstProg
5282 "C:\Program Files\MySQL\MySQL Server 5.7\bin\mysql.exe" -u testuser -p < HW_EBOOKSHOP.sql
5361 5283 ~~~ ~~~
5362 5284
5363 in Linux, or
5364
5365 ~~~{.bash}
5366 java -cp .;mysql-connector-java-***-bin.jar FirstProg
5367 ~~~
5285 for Windows.
5368 5286
5369 in Windows.
5370 The `-cp` option lists the places where java should look for the class used in the program: we are explicitely asking java to use the `mysql-connector-java-***-bin.jar` executable to execute our `FirstProg` executable.
5371 Try to execute `FirstProg` without that flag, and see what happens.
5287 You just discovered MySQL's batch mode, that perform *series* of instructions from a file.
5288 You can easily make sure that the database and the table were indeed created, and the values inserted.
5372 5289
5373
5374 Solution +.#
5375
5376 ~~~{.bash}
5377 $ java FirstProg
5378 java.sql.SQLException: No suitable driver found for jdbc:mysql://localhost:3306/HW_ebookshop
5379 at java.sql.DriverManager.getConnection(DriverManager.java:689)
5380 at java.sql.DriverManager.getConnection(DriverManager.java:247)
5381 at FirstProg.main(FirstProg.java:9)
5382 ~~~
5290 ---
5383 5291
5384 5292 Problem +.# Problem +.#
5385 ~ \ Read, execute, break, edit, compile, patch, hack and (most importantly) understand the following program:
5386
5387 ~~~{.java .numberlines}
5388 /*
5389
5390 This is a long program, introducing:
5391 I. How to pass options when connecting to the database,
5392 II. How to create a table
5393 III. How to insert values
5394 IV. How to use prepared statements
5395 V. How to read backward and write in ResultSets
5396
5397 If you want to run this program multiple times, you have to either:
5398
5399 1. Comment first statement of II. Creating a table
5400 2. Change the name of the schema, from HW_DBPROG to whatever you want
5401 3. Drop the Dvd table: connect to your database, and then enter
5402 USE HW_DBPROG;
5403 DROP TABLE Dvd;
5404 Or do it from within your program!
5405
5406 If you use option 1, you will keep inserting tuples in your table: cleaning it with
5407 DELETE FROM Dvd;
5408 can help. You can do it from within the program!
5409 */
5410
5411 import java.sql.*;
5293 ~
5412 5294
5413 public class AdvancedProg {
5414 public static void main(String[] args) {
5415 try (
5416
5417 /*
5418 * I. Passing options to the dababse
5419 */
5420
5421 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/HW_DBPROG"
5422 + "?user=testuser"
5423 + "&password=password"
5424 + "&allowMultiQueries=true"
5425 + "&createDatabaseIfNotExist=true"
5426 + "&useSSL=true");
5427
5428 // Read about other options at
5429 // https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-configuration-properties.html
5430 // https://jdbc.postgresql.org/documentation/head/connect.html
5431
5432 Statement stmt = conn.createStatement();
5433 ) {
5434
5435 /*
5436 * II. Creating a table
5437 */
5438
5439 stmt.execute("CREATE TABLE Dvd (" +
5440 "Title CHAR(25) PRIMARY KEY, " +
5441 "Minutes INTEGER, " +
5442 "Price DOUBLE)");
5443
5444 /* If we were to execute
5445 * SHOW TABLES
5446 * directly in the MySQL interpreter, this would display at the screen
5447 *
5448 * +--------------------------+
5449 * | Tables_in_HW_NewDataBase |
5450 * +--------------------------+
5451 * | Dvd |
5452 * +--------------------------+
5453 *
5454 * But here, to access this information, we will use the connection's metadata.
5455 */
5456
5457 DatabaseMetaData md = conn.getMetaData();
5458 // DatabaseMetaData is a class used to get information about the database: the driver, the user, the versions, etc.
5459
5460 ResultSet rs = md.getTables(null, null, "%", null);
5461
5462 /*
5463 * You can read at
5464 * https://docs.oracle.com/javase/7/docs/api/java/sql/DatabaseMetaData.html#getTables(java.lang.String,%20java.lang.String,%20java.lang.String,%20java.lang.String[])
5465 * the full specification of this method.
5466 * All you need to know, for now, is that the third parameter is
5467 * String tableNamePattern,
5468 * i.e., what must match the table name as it is stored in the database
5469 * Here, by using the wildcard "%", we select all the table names.
5470 * We can then iterate over the ResultSet as usual:
5471 */
5472
5473 while (rs.next()) {
5474 System.out.println(rs.getString(3)); // In the ResultSet returned by getTables, 3 is the TABLE_NAME.
5475 }
5295 This exercise supposes you successfully completed @problem:mysql_batch.
5296 We will compile and execute your first database application, using Java and MySQL.
5297
5298 - I will assume that you have MySQL installed and set-up as indicated in Homeworks \#1 and \#2.
5299 - I will assume that you have Java installed. If not, please refer to <http://spots.augusta.edu/caubert/teaching/general/java/> for a simple program and the instructions to compile and execute it.
5300 - We need to set up the *driver* (or *connector*) to make the java `sql` API and MySQL communicate. To do so,
5301 - Go to <https://dev.mysql.com/downloads/connector/j/>
5302 - Click on "Download" in front of "Platform Independent (Architecture Independent), ZIP Archive"
5303 - Look for the (somewhat hidden) "No thanks, just start my download."
5304 - You will download a file named "mysql-connector-java-***.zip", where `***` is the version number.
5305 - Upon completion of the download, unzip the file, and locate the "mysql-connector-java-***-bin.jar" file.
5306 - Copy that file in `code/java/`.
5307 - Open a terminal in that same folder, and compile `FirstProg.java`, using `javac FirstProg.java`{.bash} (or an equivalent command for windows).
5308 Normally, nothing will be printed, but a `FirstProg.class` file will be created.
5309 - Now, execute that program, using
5310 ~~~{.bash}
5311 java -cp .:mysql-connector-java-***-bin.jar FirstProg
5312 ~~~
5476 5313
5477 /*
5478 * III. Inserting values
5479 */
5480
5481 String sqlStatement = "INSERT INTO Dvd VALUES ('Gone With The Wind', 221, 3);";
5482 int rowsAffected = stmt.executeUpdate(sqlStatement);
5483 System.out.print(sqlStatement + " changed " + rowsAffected + " row(s).\n");
5314 in Linux, or
5484 5315
5485
5486 /*
5487 * Batch Insertion
5488 */
5489
5490 String insert1 = "INSERT INTO Dvd VALUES ('Aa', 129, 0.2)";
5491 String insert2 = "INSERT INTO Dvd VALUES ('Bb', 129, 0.2)";
5492 String insert3 = "INSERT INTO Dvd VALUES ('Cc', 129, 0.2)";
5493 String insert4 = "INSERT INTO Dvd VALUES ('DD', 129, 0.2)";
5494
5495 // Method 1: Using executeUpdate, if the option allowMultiQueries=true was passed in the url given to getConnection and your DBMS supports it.
5496 stmt.executeUpdate(insert1 + ";" + insert2);
5497
5498 // Method 2: Using the addBatch and executeBatch methods
5499 stmt.addBatch(insert3);
5500 stmt.addBatch(insert4);
5501 stmt.executeBatch();
5502
5503
5504 /*
5505 * IV. Prepared Statements
5506 */
5507
5508 // Example 1
5509 sqlStatement = "SELECT title FROM Dvd WHERE Price <= ?"; // We have a string with an empty slot, represented by "?".
5510 PreparedStatement ps = conn.prepareStatement(sqlStatement); // We create a PreparedStatement object, using that string with an empty slot.
5511 float maxprice = 0.5f;
5512 ps.setFloat(1, maxprice); // This statement says "Fill the first slot with the value of maxprice".
5513 ResultSet result = ps.executeQuery(); // And then we can execute the query, and display the results:
5514
5515 System.out.printf("For %.2f you can get:\n", maxprice);
5516
5517 while(result.next()){
5518 System.out.printf("\t %s \n", result.getString(1));
5519 }
5520
5521 // Example 2
5522 sqlStatement = "INSERT INTO Dvd VALUES (?, ?, ?)"; // Now, our string has 3 empty slots, and it is an INSERT statement.
5523 PreparedStatement preparedStatement = conn.prepareStatement(sqlStatement);
5316 ~~~{.bash}
5317 java -cp .;mysql-connector-java-***-bin.jar FirstProg
5318 ~~~
5524 5319
5525 preparedStatement.setString(1, "The Great Dictator");
5526 preparedStatement.setInt(2, 124);
5527 preparedStatement.setFloat(3, 5.4f);
5320 in Windows.
5321 The `-cp` option lists the places where java should look for the class used in the program: we are explicitely asking java to use the `mysql-connector-java-***-bin.jar` executable to execute our `FirstProg` executable.
5322 Try to execute `FirstProg` without that flag, and see what happens.
5528 5323
5529 rowsAffected = preparedStatement.executeUpdate(); // You can check "by hand" that this statement was correctly executed.
5530 System.out.print(preparedStatement.toString() + " changed "+ rowsAffected + " row(s).\n");
5324 Solution +.#
5325 ~
5531 5326
5532
5533 // If we try to mess things up, i.e., provide wrong datatypes:
5534 preparedStatement.setString(1, "The Great Dictator");
5535 preparedStatement.setString(2, "The Great Dictator");
5536 preparedStatement.setString(3, "The Great Dictator");
5537
5538 // Java compiler will be ok, but we'll have an error at execution time when executing the query. You can uncomment the line below to see for yourself.
5539 //rowsAffected = preparedStatement.executeUpdate();
5540
5541 // Of course, we can use prepared statement inside loops.
5542 for (int i = 1; i < 5; i++) {
5543 preparedStatement.setString(1, "Saw " + i);
5544 preparedStatement.setInt(2, 100);
5545 preparedStatement.setFloat(3, .5f);
5546 preparedStatement.executeUpdate();
5547 }
5548
5549 /*
5550 * V. Reading backward and writing in ResultSets
5551 */
5552
5553 // To read backward and write in ResultSets, you need to have a statement with certain options:
5554
5555 Statement stmtNew = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
5556
5557 /*
5558 * Those options change two things about the ResultSet we obtain using this statement
5559 *
5560 * The first argument is the scrolling level:
5561 * TYPE_FORWARD_ONLY = default.
5562 * TYPE_SCROLL_INSENSITIVE = can scroll, but updates don't impact result set.
5563 * TYPE_SCROLL_SENSITIVE = can scroll, update impact result set.
5564 *
5565 * The second argument is the concurrency level:
5566 * CONCUR_READ_ONLY: default.
5567 * CONCUR_UPDATABLE: we can change the database without issuing SQL statement.
5568 */
5569
5570 /*
5571 * Reading backward
5572 */
5573
5574 sqlStatement = "SELECT title FROM Dvd WHERE Price < 1;";
5575 result = stmtNew.executeQuery(sqlStatement);
5327 ~~~{.bash}
5328 $ java FirstProg
5329 java.sql.SQLException: No suitable driver found for jdbc:mysql://localhost:3306/HW_EBOOKSHOP
5330 at java.sql.DriverManager.getConnection(DriverManager.java:689)
5331 at java.sql.DriverManager.getConnection(DriverManager.java:247)
5332 at FirstProg.main(FirstProg.java:9)
5333 ~~~
5576 5334
5577 System.out.println("For $1, you can get:");
5578
5579 if (result.last()) { // We can jump to the end of the ResultSet
5580 System.out.print(result.getString("Title") + " ");
5581 }
5582
5583 System.out.print("and also, (in reverse order)");
5584
5585 while (result.previous()) { // Now we can scroll back!
5586 System.out.print(result.getString("Title") + " ");
5587 }
5588
5589 /*
5590 * Other methods to navigate in ResultSet:
5591 * first()
5592 * last()
5593 * next()
5594 * previous()
5595 * relative(x) : move cursor x times (positive = forward, negative = backward)
5596 * absolute(x): move to the row number x. 1 is the first.
5597 */
5598
5599 /*
5600 * Changing the values
5601 */
5602
5603 System.out.print("\n\nLet us apply a 50% discount. Currently, the prices are:\n");
5604
5605 sqlStatement = "SELECT title, price FROM Dvd;";
5606 result = stmtNew.executeQuery(sqlStatement);
5607 while (result.next()) {
5608 System.out.printf("%20s \t $%3.2f\n", result.getString("title") , result.getDouble("price"));
5609 }
5610
5611
5612 result.absolute(0); // We need to scroll back!
5613
5614 while (result.next()) {
5615 double current = result.getDouble("price");
5616 result.updateDouble("price", (current * 0.5));
5617 result.updateRow();
5618 }
5619 System.out.print("\n\nAfter update, the prices are:\n");
5620
5621 result.absolute(0); // We need to scroll back!
5622
5623 while (result.next()) {
5624 System.out.printf("%20s \t $%3.2f\n", result.getString("title") , result.getDouble("price"));
5625 }
5626
5627
5628 conn.close();
5629 } catch (SQLException ex) {
5630 ex.printStackTrace();
5631 }
5632 }
5633 }
5634 ~~~
5635
5335 Problem +.#
5336 ~
5636 5337
5338 Read, execute, break, edit, compile, patch, hack and (most importantly) understand the following program:
5637 5339
5340 ```{.sqlmysql .numberLines include=code/java/AdvancedProg.java}
5341 ```
5638 5342
5639 5343 --- ---
5640 5344
 
... ... public class AdvancedProg {
5648 5352
5649 5353 - Who is threatening you? - Who is threatening you?
5650 5354 - What are the risks? - What are the risks?
5651
5652 5355 #. Loss of integrity (improper modification) #. Loss of integrity (improper modification)
5653 5356 #. Loss of availability #. Loss of availability
5654 5357 #. Loss of confidentiality (unauthorized disclosure) #. Loss of confidentiality (unauthorized disclosure)
5655
5656 5358 - "You are as strong as your weakest link." - "You are as strong as your weakest link."
5657 5359 - Never trust the user or their computer. - Never trust the user or their computer.
5658 5360
5361
5659 5362 ### Control measures ### Control measures
5660 5363
5661 5364 - Access control (user account, passwords, restrictions) - Access control (user account, passwords, restrictions)
 
... ... Think of BSON as a binary representation of JSON (JavaScript Object Notation) do
5880 5583
5881 5584 An example of XML (Extensible Markup Languag) document (you can actually convert from XML to JSON): An example of XML (Extensible Markup Languag) document (you can actually convert from XML to JSON):
5882 5585
5883 ~~~{.xml}
5586 ~~~{.xml .numberLines}
5884 5587 <shiporder orderid="889923"> <shiporder orderid="889923">
5885 5588 <orderperson>John Smith</orderperson> <orderperson>John Smith</orderperson>
5886 5589 <shipto> <shipto>
 
... ... Each MongoDB instance has multiple databases, each database can have multiple co
5921 5624
5922 5625 Two documents (delimited by `[`…`]`, used to delimit an arry of document). Two documents (delimited by `[`…`]`, used to delimit an arry of document).
5923 5626
5924 ~~~{.json}
5627 ~~~{.json .numberLines}
5925 5628 [ [
5926 5629 { {
5927 5630 "firstname": "Martin", "firstname": "Martin",
 
... ... db.collection.find()
6076 5779
6077 5780 We can construct lists of documents and insert them: We can construct lists of documents and insert them:
6078 5781
6079 ~~~{.java}
5782 ~~~{.java .numberLines}
6080 5783 List<Document> documents = new ArrayList<Document>(); List<Document> documents = new ArrayList<Document>();
6081 5784 for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
6082 5785 documents.add(new Document("i", i)); documents.add(new Document("i", i));
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/caubert/CSCI_3410

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/caubert/CSCI_3410

Clone this repository using git:
git clone git://git.rocketgit.com/user/caubert/CSCI_3410

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main