Copyright © 2019 Oracle and/or its affiliates. MySQL Connector/J in the Making of Modern Applications

Filipe Silva Connector/J Developer and Team Lead MySQL Middleware and Clients September 17, 2019

Copyright © 2019 Oracle and/or its affiliates. Safe Harbor

The following is intended to outline our general product direction. It is intended for information purposes only, and may not be incorporated into any contract. It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. The development, release, timing, and pricing of any features or functionality described for Oracle’s products may change and remains at the sole discretion of .

Statements in this presentation relating to Oracle’s future plans, expectations, beliefs, intentions and prospects are “forward-looking statements” and are subject to material risks and uncertainties. A detailed discussion of these factors and other risks that affect our business is contained in Oracle’s Securities and Exchange Commission (SEC) filings, including our most recent reports on Form 10-K and Form 10-Q under the heading “Risk Factors.” These filings are available on the SEC’s website or on Oracle’s website at http://www.oracle.com/investor. All information in this presentation is current as of September 2019 and Oracle undertakes no duty to update any statement in light of new information or future events.

Copyright © 2019 Oracle and/or its affiliates. Filipe Silva

Connector/J Developer and Team Lead MySQL Middleware and Clients September 17, 2019 [email protected]

Copyright © 2019 Oracle and/or its affiliates. What Developers Want? MySQL Provides!

{“topic”: 1} Modern Applications Architecture {“topic”: 5} MySQL Document Store

{“topic”: 2} How Data Flows and Looks Like? {“topic”: 6} What is the X DevAPI?

{“topic”: 3} JSON, the Binding Glue {“topic”: 7} Connector/J with X DevAPI

{“topic”: 4} NoSQL to the Rescue {“topic”: 8} Closing Comments, Q & A

Copyright © 2019 Oracle and/or its affiliates. What Developers Want?

Developers demand challenging, interesting projects. In a quest for learning something new, developers are more than willing to explore new tools, technologies or processes. The ultimate goal is to do more with less.

Copyright © 2019 Oracle and/or its affiliates. Modern Applications Architecture

 Ever-growing demand for containerized microservices  Extreme scalability, extreme decoupling and extreme agility  In isolation, a single microservice could be seen almost as an independent, lightweight, minimalist 3-tier architecture  Except that they usually are stateless and pipeline-ready

Copyright © 2019 Oracle and/or its affiliates. Microservices Architecture

Microservice Microservice Data Store

User Microservice Interface Microservice Data Store

Microservice Microservice Data Store

Copyright © 2019 Oracle and/or its affiliates. 3-Tier Architecture

Presentation Logic Data

Web/Application User Interface Database Servers Servers

Workflow Relational and UI JavaScript Systems & NoSQL Frameworks Business Logic Databases

Copyright © 2019 Oracle and/or its affiliates. How Data Flows?

Client requests data or operation JSON

Server Client receives the renders the client response JSON request

JSON

Server builds Sever and replies a processes Data Store response operation JSON

Copyright © 2019 Oracle and/or its affiliates. How Data Looks Like?

From a DBA perspective From a developer perspective

{ "_id": "5bc1195b6f36a842a4f65b24", "age": 21, "name": { "first": "Vicky", "last": "Leonard" }, "company": "CodeONE", "email": "[email protected]", "phone": "+1 (864) 428-3897", "address": "506 Broadway, Jeff, Ohio, 2249", "tags": ["", "development", "database“] }

Copyright © 2019 Oracle and/or its affiliates. JSON, the Binding Glue

 JSON: “JavaScript Object Notation”  Name/value pairs, array data and other serializable types  Cross-platform serialization format  Widely used in web services and microservices  Standardized as ECMA-404 and RFC 8259  Natively supported by MySQL  Specific data type and multiple functions to operate on JSON values and columns

Copyright © 2019 Oracle and/or its affiliates. NoSQL to the Rescue

 NoSQL: “Not Only SQL”  Many types of NoSQL  Developers don’t like SQL systems, little uniformity among them  NoSQL promises to scale and  Key-Value Database make applications agile Oracle NoSQL Database, Redis, , Memcached  Document-oriented Database  “Schema-free”/“Schema-less” Apache CouchDB, MongoDB, Couchbase built on distributed systems  Wide Column Store Bigtable, Apache Cassandra, Apache HBase  Relaxed ACID principles  Graph Neo4j, JanusGraph, AllegroGraph

Copyright © 2019 Oracle and/or its affiliates. MySQL Provides!

We hear our customers. Always evolving, sometimes re-inventing itself, MySQL keeps pace with the trends and drives for success of its users. Either improving existing features or providing new ones, either increasing its impressive toolset or stepping into the Cloud, MySQL provides!

Copyright © 2019 Oracle and/or its affiliates. What If… Schema and schema-less co-existed together in the same technology stack?

Developers Operations Business Owners

Simultaneous  Comprehensive  Don’t lose my data Schema-less and tooling ecosystem  ACID compliant schema based Performance Capture all my data development management  Extensible, Scalable Rapid prototyping  Robust replication, Products on backup and restore Document based schedule   Affordable time to model Simpler application market schema upgrades Transactions  Fast development

Copyright © 2019 Oracle and/or its affiliates. NoSQL SQL + SQL = NoSQL

Copyright © 2019 Oracle and/or its affiliates. MySQL Document Store

An easy, straightforward way of working with JSON documents in MySQL

Copyright © 2019 Oracle and/or its affiliates. MySQL Document Store

 Store unstructured data using a MySQL database  No explicit schemas and data types  Data lives in JSON columns…  That are abstracted away from the user, which only deals with documents  CRUD operations…  SQL not mandatory but available  Consistency and data integrity…  Fully ACID compliant MySQL RDBMS and InnoDB engine in the background  Documents and relational tables mixed together

Copyright © 2019 Oracle and/or its affiliates. MySQL Document Store

Client Application MySQL Server

MySQL Router

X DevAPI X Plugin (Connector)

MySQL Protocol X Protocol

Copyright © 2019 Oracle and/or its affiliates. X DevAPI

High-level database API to Available in many popular develop CRUD-based programming languages and in applications with off-the-shelf the MySQL Shell. Documents NoSQL document operations. and relational tables in one single place.

Provides many expert-level Empowered by clustered features, including raw SQL, MySQL setups seamlessly transactions, locking, prepared integrated with InnoDB statements and more. clusters and MySQL Router.

Copyright © 2019 Oracle and/or its affiliates. MySQL Router

MySQL Router is A standalone, Provides high an integral part of lightweight, availability and the InnoDB cluster, middleware for scalability to client a solution for high transparent applications and is availability that routing between available for Linux, relies on MySQL applications and MacOS and Group Replication. MySQL Servers. Windows.

Copyright © 2019 Oracle and/or its affiliates. X Plugin

The MySQL server Document storage Implements a plugin that layer on existing MySQL installations new client-server supports the entire by enabling the protocol – the X MySQL Document bridge between the Protocol. Store solution on X DevAPI and the the server side. core MySQL engine.

Copyright © 2019 Oracle and/or its affiliates. X Protocol

A new client-server Simple packets with Security baked-in protocol based on structured content. SQL replaced by CRUD with TLS enabled Google Protocol operation trees with by default. No Buffers. Uses embedded parameter information leaks improved data binding. Messages can out to non- streaming technics be pipelined and such as Vectored wrapped by conditional authenticated I/O or Pipelining. expectations. users.

Copyright © 2019 Oracle and/or its affiliates. Protocol Buffer Message Sample

Mysqlx.Crud.Find { collection { name: "collection_name", schema: “schema_name" } data_model: DOCUMENT criteria { type: OPERATOR operator { name: "==" param { type: IDENT, identifier { name: "_id" } } param { type: LITERAL, literal { type: V_STRING, v_string: { value: "some_string" } } } } } }

Copyright © 2019 Oracle and/or its affiliates. What is the X DevAPI?

MySQL’s cross-platform, language agnostic, API for clients connecting to MySQL servers as a Document Store and classic RDBMS

Copyright © 2019 Oracle and/or its affiliates. Key Features

 Enables MySQL Document Store  Synchronous and Asynchronous to client applications operation executions  Offers schema-less data storage  Secure by default (TLS+SHA2) development  Transactions, save points and row-locking  Fluent API  Programming language agnostic  Auto-magic prepared  Intuitive CRUD methods statements  Raw SQL also available  Connection pooling and fail-  Domain specific expression over language  Integrated in the MySQL Shell

Copyright © 2019 Oracle and/or its affiliates. Schema-less Documents

 Documents are JSON structures  Open standard, language-independent file format  Human-readable text  Uniquely identified by one attribute – "_id" – that exists in all documents

Copyright © 2019 Oracle and/or its affiliates. Schema-less Collections

 Collections are containers of Documents  The Document structure within a single Collection can vary significantly  Technically, a Collection is an InnoDB table  One regular column of type JSON – "doc"  One virtual column for document id – "_id", also the table primary key  Multiple virtual columns that grab data from the JSON structures for indexing and enforcing constraints

Copyright © 2019 Oracle and/or its affiliates. Fluent API

 Code flows from a single point of entry – getSession()  First-class support for IDE hints and auto-completion  Operations encapsulated in specialized and semantic methods  Nice scaffolding for repeating tasks  Smaller SQL injection surface area  Code becomes more readable, maintainable, and even testable  Common standard between many popular programming languages

Copyright © 2019 Oracle and/or its affiliates. JS> users.add({ name: "Filipe" }).add({ name: "Alex" }) Query OK, 2 items affected (0.0373 sec)

CRUD Operations JS> users.find() [ { "_id": "00005b50ced40000000000000001", "name": "Filipe" },  { Modern and versatile "_id": "00005b50ced40000000000000002", "name": "Alex" CRUD API } ]  Semantic Document Store 2 documents in set (0.0009 sec) methods JS> users.modify("true").set("team", "connector-java") Query OK, 2 items affected (0.0751 sec)  Manage data without JS> users.find('name = "Filipe"') [ { writing a single line of SQL "_id": "00005b50ced40000000000000001", "name": "Filipe", "team": "connector-java" } ] 1 document in set (0.0026 sec)

Copyright © 2019 Oracle and/or its affiliates. Raw SQL

 Suitable for ETL, structured analytics and reporting  Open door to features not yet in the X DevAPI, such as:  DDL operations for relational tables  Managing key constraints  Joining tables

JS> session.sql('CREATE TABLE data1 (doc JSON)')

JS> session.sql('ALTER TABLE data1 ADD COLUMN name VARCHAR(100) GENERATED ALWAYS AS doc->>"$.name“ VIRTUAL UNIQUE KEY NOT NULL')

JS> session.sql('SELECT DISTINCT t1.name, t2.address FROM data1 t1 JOIN data2 t2 ON t1.name = t2.name WHERE t2.age > 21').execute()

Copyright © 2019 Oracle and/or its affiliates. Method Chaining and Flexible Parameters

 Repeated method calls with individual arguments  A single list of a variable number of arguments

JS> collection.add({ name: "Ann" }).add({ name: "Peter" }) JS> collection.add([{ name: "John" }, { name: "Mark" }])

JS> collection.find('name = :name').bind('name', 'Ann') JS> collection.find('name = :name').bind({ name: "John" })

JS> collection.find().fields('name', 'age') JS> collection.find().fields(['name', 'age'])

Copyright © 2019 Oracle and/or its affiliates. Domain Specific Expressions Language

 Meaningful and human readable  Resemble closely SQL expressions – subset of it  Support for most of MySQL operators and functions  Document paths and table/column reference identifiers  Named placeholders  Common between all official connector implementations  Translated to expression trees in the X Protocol

Copyright © 2019 Oracle and/or its affiliates. Secure by Default

 TLS is enabled by default in TCP based sessions  Additional server certificate validation options  Default options can be overridden on-demand

 SHA-1 and SHA-2 password hashing, used in non-secure connections  Support for the main server authentication plugins  caching_sha2_password  sha256_password  mysql_native_password

Copyright © 2019 Oracle and/or its affiliates. Transactions and Savepoints

try { session.startTransaction()  Session-level atomic // run some operations (1) session.createSavepoint("here") operations // run more operations (2) session.releaseSavepoint("here")  Create, commit or rollback session.commit() transactions in the scope of } catch (err) { try { a session session.rollbackTo("here") // go to (2)  Create, release or rollback to } catch (err) { session.rollback() // revert the entire thing intermediate savepoints in } those transactions }

Copyright © 2019 Oracle and/or its affiliates. Row (Document) Locking

 Reads determine isolation level in the presence of concurrent transactions  Exclusive and Shared locks with two operation modes besides DEFAULT (active waiting until unlocked):  NOWAIT, terminates with error  SKIP_LOCKED, skips locked rows/documents

Copyright © 2019 Oracle and/or its affiliates. Auto-magic Prepared Statements

 Repeated executions of same statement causes it to be server- side prepared  New values are passed via parameter binding  Changes in statement definition triggers re-prepare on next execution  Paging operations (limit() and offset()) only trigger re-prepare the first time they are set.

Copyright © 2019 Oracle and/or its affiliates. Connection Pooling

 Out-of-the-box connection pooling support – no external libraries needed  Reduce overhead for applications that open many connections  Pooled connections are automatically managed by a Client object  Simplified setup: timeouts and maximum size

Copyright © 2019 Oracle and/or its affiliates. Connector/J with X DevAPI

MySQL’s flagship connector for Java programming language that combines the traditional JDBC API and the new MySQL X DevAPI in one single driver

Copyright © 2019 Oracle and/or its affiliates. MySQL Connector/J Overview

 MySQL develops and maintains two Connector/J versions – 8.0 and 5.1  Open source hosted in GitHub  https://github.com/mysql/mysql-connector-j  Available from MySQL downloads page and maven Central Repository  Connector/J 8.0 is GA and the recommended version

Copyright © 2019 Oracle and/or its affiliates. MySQL Connector/J 8.0

 Available since Aug. 2015  Type 4 JDBC driver  Compliant with JDBC 4.2 (Java 8.0)  Requires Java 8 or above  Supports MySQL Protocol and X Protocol  Implements the X DevAPI  Compatible with MySQL 5.5 and above

Copyright © 2019 Oracle and/or its affiliates. X DevAPI Connetion Objects Package: com.mysql.cj.xdevapi

ClientFactory Static factory to create Client objects with specific pooling and session configurations Client Creates sessions and manages a pool of Session instances SessionFactory Static factory to create Session objects with specific session configurations

Session Establishes and maintains X Protocol connections

Copyright © 2019 Oracle and/or its affiliates. Main Data Objects Package: com.mysql.cj.xdevapi

Session Entry point for all data operations; Provides means to manage schemas and enables raw SQL operations Schema Equivalent to a MySQL database; Manages collections and tables Collection Document storage and management; It’s a MySQL table with a specific structure Table Classic MySQL table Result Result of data manipulation operations (.add(), .insert(), .modify(), …) DocResult Result of document fetching from collections DbDoc Single document obtained from a DocResult RowResult Result of selecting data from tables (via table.select()) SqlResult Result of selecting data from raw SQL (via session.sql()) Row Single row of data from a RowResult or SqlResult

Copyright © 2019 Oracle and/or its affiliates. JSON Data and Parsing Package: com.mysql.cj.xdevapi

JsonParser Transforms JSON documents in string form into DbDoc or JsonArray objects

DbDoc Represents a JSON object, i.e., a collection of name/value pairs JsonArray Represents a JSON ordered list of values JsonString Represents a JSON string JsonNumber Represents a JSON number JsonLiteral Represents one of the three JSON literals: true, false and null

JsonValue Interface that represents a generic JSON value, i.e., any of the above except JsonParser

Copyright © 2019 Oracle and/or its affiliates. Show Case

Back-end system from managing “guests” that book into the historical…

Hotel Alcatraz the ultimate luxury destination!

Copyright © 2019 Oracle and/or its affiliates. Core X DevAPI Features

Copyright © 2019 Oracle and/or its affiliates. Creating a Session

SessionFactory sf = new SessionFactory();

Session session1 = sf.getSession("mysqlx://demousr:demopwd@localhost"); Session session2 = sf.getSession( "mysqlx://demousr:demopwd@localhost?xdevapi.ssl-mode=DISABLED");

// Your code goes here! session1.close(); session2.close();

 X DevAPI URL format: mysqlx://:@:/?&...

Copyright © 2019 Oracle and/or its affiliates. Creating a Pooled Session

ClientFactory cf = new ClientFactory();

Client client = cf.getClient("mysqlx://demousr:demopwd@localhost:33060", "{ \"pooling\" : { \"enabled\": true, \"maxSize\": 10 } }");

Session session = client.getSession();

// Your code goes here! session.close(); client.close();

 Connection pooling options: { pooling : { enabled: , maxSize: , maxIdleTime: , queueTimeOut: } }

Copyright © 2019 Oracle and/or its affiliates. Creating and Managing Schemas session.createSchema("alcatraz", true); // reuse existing session.createSchema("escape");

List schemas = session.getSchemas(); schemas.forEach(System.out::println); | Schema(alcatraz) | Schema(escape)

// Schema "escape" was a mistake, let’s drop it session.dropSchema("escape"); session.getSchemas().forEach(System.out::println); | Schema(alcatraz)

Copyright © 2019 Oracle and/or its affiliates. Creating and Managing Schemas

SQL> show databases; session.createSchema("alcatraz", true); // reuse existing +------+ session.createSchema("escape"); | Database | +------+ List schemas = session.getSchemas(); | alcatraz | schemas.forEach(System.out::println); | information_schema | | Schema(alcatraz) | mysql | | Schema(escape) | performance_schema | | sys | // Schema "escape" was a mistake, let’s drop it +------+ session.dropSchema("escape"); 5 rows in set (0.0041 sec) session.getSchemas().forEach(System.out::println); | Schema(alcatraz) SQL>

Copyright © 2019 Oracle and/or its affiliates. Creating and Managing Collections …

Session session = sf.getSession("mysqlx://demousr:demopwd@localhost/alcatraz");

Schema schema = session.getDefaultSchema();

Collection colR = schema.createCollection("rooms", true); Collection colI = schema.createCollection("checkins", true); Collection colO = schema.createCollection("checkouts"); schema.getCollections().forEach(System.out::println); | Collection(alcatraz.checkins) | Collection(alcatraz.checkouts) | Collection(alcatraz.rooms)

Copyright © 2019 Oracle and/or its affiliates. Creating and Managing Collections …

SQL> use alcatraz Session session = Default schema set to `alcatraz`. sf.getSession("mysqlx://demousr:demopwd@localhost/alcatraz"); SQL> show tables; Schema schema = session.getDefaultSchema(); +------+ | Tables_in_alcatraz | Collection colR = schema.createCollection("rooms", true); +------+ Collection colI = schema.createCollection("checkins", true); | checkins | Collection colO = schema.createCollection("checkouts"); | checkouts | | rooms | schema.getCollections().forEach(System.out::println); +------+ | Collection(alcatraz.checkins) 3 rows in set (0.0045 sec) | Collection(alcatraz.checkouts) | Collection(alcatraz.rooms) SQL>

Copyright © 2019 Oracle and/or its affiliates. … Creating and Managing Collections schema.getCollections("check%").forEach(System.out::println); | Collection(alcatraz.checkins) | Collection(alcatraz.checkouts)

System.out.println(schema.getCollectionAsTable("rooms")); | Table(alcatraz.rooms)

// Collection "checkouts" was a mistake, let’s drop it schema.dropCollection("checkouts");

Copyright © 2019 Oracle and/or its affiliates. … Creating and Managing Collections

SQL> show tables; +------+ schema.getCollections| Tables_in_alcatraz("check%").| forEach(System.out::println); | Collection(+------alcatraz.checkins+ ) | checkins | | Collection(| roomsalcatraz.checkouts | ) +------+ 2 rows in set (0.0057 sec) System.outSQL.println> desc rooms;(schema.getCollectionAsTable("rooms")); +------+------+------+-----+------+------+ | Table(alcatraz.rooms| Field | Type ) | Null | Key | Default | Extra | +------+------+------+-----+------+------+ | doc | | YES | | NULL | | | _id | varbinary(32) | NO | PRI | NULL | STORED GENERATED | // Collection+------"checkouts+------" was+ ------a mistake,+-----+------let’s +drop------it + schema.dropCollection2 rows in set (0.0053("checkouts sec) "); SQL>

Copyright © 2019 Oracle and/or its affiliates. Sample Data

[ { { "name": "George Kelly Barnes", "name": "Arthur Barker", "nick": "Machine Gun Kelly", "nick": "Doc", "inmate": 117, "inmate": 268, "crimes": "crimes": [ "Robbery", "Murder" ] [ "Kidnapping", "Murder" ] }, }, { { "name": "Robert Franklin Stroud", "name": "Alphonse AL Capone", "nick": "Birdman", "nick": "Scarface", "inmate": 594, "inmate": 85, "crimes": "crimes": [ "Murder" ] [ "Mafia", "Tax evasion" ] } }, ]

Copyright © 2019 Oracle and/or its affiliates. Adding Documents …

String g1 = "{\"name\": \"Arthur Barker\", " + "\"nick\": \"Doc\", \"inmate\": 268}"; DbDoc d1 = JsonParser.parseDoc(g1);

String g2 = "{\"name\": \"AL Capone\", \"nick\": " + "\"Scarface\", \"inmate\": 85, \"crimes\": [\"Mafia\"]}"; DbDoc d2 = JsonParser.parseDoc(g2);

AddResult res = col.add(d1).add(d2).execute(); res.getGeneratedIds().forEach(System.out::println); | 00005d7381020000000000000001 | 00005d7381020000000000000002

Copyright © 2019 Oracle and/or its affiliates. … Adding Documents

String g3 = "{\"name\": \"George Kelly Barnes\", " + "\"nick\": \"Machine Gun Kelly\", \"inmate\": 117, " + "\"crimes\": [\"Robbery\", \"Murder\"]}"; String g4 = "{\"name\": \"Robert Franklin Stroud\", \"nick\": " + "\"Batman\", \"inmate\": 594, \"crimes\": [\"Murder\"]}";

CompletableFuture cfRes = col.add(g3, g4).executeAsync(); res = cfRes.get(); res.getGeneratedIds().forEach(System.out::println); | 00005d7381020000000000000003 | 00005d7381020000000000000004

Copyright © 2019 Oracle and/or its affiliates. … Adding Documents

SQL> select _id, LEFT(doc, 54) from alcatraz.checkins; String g3 +=------"{\"name\": \"George Kelly+------Barnes\", " + + "\|"nick _id \ ": \ "Machine Gun Kelly| LEFT(doc,\", \ "inmate54) \ ": 117, " + | +------+------+ "\|"crimes 00005d7381020000000000000001\": [\"Robbery\", | \{"_id":"Murder "00005d7381020000000000000001",\"]}"; "name": "Arthu | String g4 |= 00005d7381020000000000000002 "{\"name\": \"Robert Franklin| {"_id": "00005d7381020000000000000002",Stroud\", \"nick\": " + "name": "AL Ca | | 00005d7381020000000000000003 | {"_id": "00005d7381020000000000000003", "name": "Georg | "\|" 00005d7381020000000000000004Batman\", \"inmate\": 594,| {"_id": \"crimes "00005d7381020000000000000004",\": [\"Murder\"]}"; "name": "Rober | +------+------+ CompletableFuture4 rows in )cfRes = col.add(g3, g4).executeAsync(); SQL> res = cfRes.get(); res.getGeneratedIds().forEach(System.out::println); | 00005d7381020000000000000003 | 00005d7381020000000000000004

Copyright © 2019 Oracle and/or its affiliates. Modifying Documents …

JsonArray crimes = JsonParser.parseArray(new StringReader("[\"Kidnapping\", \"Murder\"]"));

ModifyStatement modSt = col.modify("inmate = :im").bind("im", 268);

Result res = modSt.set("crimes", crimes).execute(); System.out.println(res.getAffectedItemsCount()); | 1

// {"_id":"...01","crimes":["Kidnapping","Murder"],"inmate":268,...}

Copyright © 2019 Oracle and/or its affiliates. … Modifying Documents res = modSt.bind("im", 85).arrayAppend("crimes", "Tax Evasion").patch( "{\"name\": CONCAT(\"Alphonse \", $.name), \"crimes\": $.crimes}") .execute(); System.out.println(res.getAffectedItemsCount()); | 1

// {"_id":"...2","crimes":["Mafia","Tax Evasion"],"name":"Alphonse AL Capone,...} res = col.modify("_id LIKE '%004'").set("nick", "Birdman").execute(); System.out.println(res.getAffectedItemsCount()); | 1

// {"_id":"...4","nick":"Birdman",...}

Copyright © 2019 Oracle and/or its affiliates. … Modifying Documents

SQL> select doc->'$.name', doc->'$.nick', doc->'$.crimes' from checkins; res = modSt.bind("im+------", 85).arrayAppend("crimes",+------"Tax Evasion").patch(+------+ "{\"name\":| CONCAT(doc->'$.name'\"Alphonse \ ", | doc$.name),->'$.nick' \ "crimes | doc\":->'$.crimes' $.crimes}") | .execute();+------+------+------+ | "Arthur Barker" | "Doc" | ["Kidnapping", "Murder"] | System.out.println(|res.getAffectedItemsCount "Alphonse AL Capone" | "Scarface"()); | ["Mafia", "Tax Evasion"] | | 1 | "George Kelly Barnes" | "Machine Gun Kelly" | ["Robbery", "Murder"] | | "Robert Franklin Stroud" | "Birdman" | ["Murder"] | +------+------+------+ // {"_id":"...2","crimes":["4 rows in setMafia","Tax (0.0032 sec) Evasion"],"name":"Alphonse AL Capone,...} SQL> res = col.modify("_id LIKE ‘%004'").set("nick", "Birdman").execute(); System.out.println(res.getAffectedItemsCount()); | 1

// {"_id":"...4","nick":"Birdman",...}

Copyright © 2019 Oracle and/or its affiliates. Fetching Documents …

// Find all documents: col.find().execute().forEach(System.out::println); | {"_id":"...01","name":"Arthur Barker","nick":"Doc",...} | {"_id":"...02","name":"Alphonse AL Capone","nick":"Scarface",...} | {"_id":"...03","name":"George Kelly Barnes","nick":"Machine Gun Kelly",...} | {"_id":"...04","name":"Robert Franklin Stroud","nick":"Birdman",...}

// Find documents with "length(crimes) = 1" DocResult res = col.find("JSON_LENGTH($.crimes) = :cr").bind("cr", 1) .execute(); System.out.println(res.count()); | 1 res.forEach(System.out::println); | {"_id":"...04","crimes":["Murder"],"name":"Robert Franklin Stroud"...}

Copyright © 2019 Oracle and/or its affiliates. … Fetching Documents

// Using projections: col.find("inmate > 200").fields("UPPER(nick) AS nk, LEFT(name, 6) AS nm") .execute().forEach(System.out::println); | {"nk":"DOC","nm":"Arthur"} | {"nk":"BIRDMAN","nm":"Robert"} col.find("inmate > 200").fields(Expression.expr("{'nk': UPPER(nick), " + "'nm': LEFT(name, 6)}")).execute(); // Alternative to previous

// Find in array values, sort by "inmate": col.find("'Murder' IN $.crimes").sort("inmate ASC").execute() .forEach(System.out::println); | {"_id":"...03","crimes":["Robbery","Murder"],"inmate":117,...} | {"_id":"...01","crimes":["Kidnapping","Murder"],"inmate":268,...} | {"_id":"...004","crimes":["Murder"],"inmate":594,...}

Copyright © 2019 Oracle and/or its affiliates. Deleting Documents col.add("{\"name\": \"O. J. Simpson\", \"nick\": \"The Juice\", " + "\"inmate\": 32, \"crimes\": [\"Murder\"]}").execute(); col.add("{\"name\": \"O. J. Simpson\", \"nick\": \"The Juice\", " + "\"inmate\": 32, \"crimes\": [\"Robbery\"]}").execute(); col.add("{\"name\": \"O. J. Simpson\", \"nick\": \"The Juice\", " + "\"inmate\": 32, \"crimes\": [\"Kidnapping\"]}").execute();

Result res = col.removeOne("00005d7381020000000000000004"); System.out.println(res.getAffectedItemsCount()); | 1 res = col.remove("nick LIKE '%Juice%'").execute(); System.out.println(res.getAffectedItemsCount()); | 2

Copyright © 2019 Oracle and/or its affiliates. Advanced and Other X DevAPI Features

Copyright © 2019 Oracle and/or its affiliates. Document/Row Locking Reads

Session session1 = sf.getSession("mysqlx://demousr:demopwd@localhost/alcatraz"); Session session2 = sf.getSession("mysqlx://demousr:demopwd@localhost/alcatraz");

Collection col1 = session1.getDefaultSchema().getCollection("checkins"); Collection col2 = session2.getDefaultSchema().getCollection("checkins"); session1.startTransaction(); session2.startTransaction(); col1.find("_id = '00005d7381020000000000000001'").fields("name AS nm, nick AS nk, " + "inmate AS im").lockShared().execute().forEach(System.out::println); | {"im":268,"nk":"Doc","nm":"Arthur Barker"} col2.find().fields("name AS nm, nick AS nk, inmate AS im") .lockExclusive(LockContention.SKIP_LOCKED).execute().forEach(System.out::println); | {"im":85,"nk":"Scarface","nm":"Alphonse AL Capone"} | {"im":117,"nk":"Machine Gun Kelly","nm":"George Kelly Barnes"} | {"im":594,"nk":"Birdman","nm":"Robert Franklin Stroud"}

Copyright © 2019 Oracle and/or its affiliates. Indexes on Documents

Session session = sf.getSession("mysqlx://demousr:demopwd@localhost/alcatraz"); Collection col = session.getDefaultSchema().getCollection("checkins"); col.createIndex("byInmate", "{\"fields\": [{\"field\": \"$.inmate\", \"type\": \"INTEGER\"}]}"); session.close();

 Also supports indexing JSON array fields: { fields: [ { field: "$.crimes", type: "TEXT(50)", array: true } ] }

Copyright © 2019 Oracle and/or its affiliates. Indexes on Documents

SQL> show create table checkins; Session+------session+------= sf.getSession("mysqlx://demousr:demopwd@localhost/alcatraz"); + Collection| Table col | Create= session.getDefaultSchema Table (). getCollection (" checkins "); | +------+------+ | checkins | CREATE TABLE `checkins` ( col.createIndex("`doc`byInmate json",DEFAULT NULL, "{\"fields\":`_id` [{\ "fieldvarbinary\":(32) \"$.inmate GENERATED\ ",ALWAYS \"type AS \": \"INTEGER\"}]}"); (json_unquote(json_extract(`doc`,_utf8mb4'$._id'))) STORED NOT NULL, session.close(); `$ix_i_92928B93F64A9D89EA3915487DC534EA3E9DBE62` int(11) GENERATED ALWAYS AS (json_extract(`doc`,_utf8mb4'$.inmate')) VIRTUAL, PRIMARY KEY (`_id`), KEY `byInmate` (`$ix_i_92928B93F64A9D89EA3915487DC534EA3E9DBE62`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |  Also+------supports+------indexing JSON array fields: + 1 row in set (0.0028 sec) { fields: [ { field: "$.crimes", type: "TEXT(50)", array: true } ] } SQL>

Copyright © 2019 Oracle and/or its affiliates. Working with Tables …

SQL> create table alcatraz.teams (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, name varchar(100)); Query OK, 0 rows affected (0.0655 sec)

SQL> Consumer rowPrinter = r -> System.out.println(r.getInt(0) + " -> " + r.getString(1)); Table table = schema.getTable("teams");

InsertResult res = table.insert("name") .values("Giants").values("Warriors").values("Glens").execute(); System.out.println(res.getAffectedItemsCount() + "/" + res.getAutoIncrementValue()); | 3/1 table.select().execute().forEach(rowPrinter); | 1 -> Giants | 2 -> Warriors | 3 -> Glens table.select().orderBy("name").execute().forEach(rowPrinter); | 1 -> Giants | 3 -> Glens | 2 -> Warriors

Copyright © 2019 Oracle and/or its affiliates. … Working with Tables table.update().where("name = 'Glens'") .set("name", Expression.expr("CONCAT(name, ' SC')")).execute(); table.select().execute().forEach(rowPrinter); | 1 -> Giants | 2 -> Warriors | 3 -> Glens SC table.delete().where("name LIKE 'G%'").execute(); table.select().execute().forEach(rowPrinter); | 2 -> Warriors table.delete().execute(); table.select().execute().forEach(rowPrinter); |

Copyright © 2019 Oracle and/or its affiliates. Raw SQL

SqlResult res = session.sql("INSERT INTO teams (name) " + "VALUES ('Deltas'), ('Golden Gate')").execute(); System.out.println(res.getAffectedItemsCount() + "/" + res.getAutoIncrementValue()); | 2/4 res = session.sql("SELECT * FROM teams").execute(); res.forEach(rowPrinter); | 4 --> Deltas | 5 --> Golden Gate res.getColumns().stream().map(Column::getType).forEach(System.out::println); | INT | STRING session.sql("DELETE FROM teams").execute(); session.sql("SELECT * FROM teams").execute().forEach(rowPrinter); | session.sql("DROP TABLE teams").execute();

Copyright © 2019 Oracle and/or its affiliates. Closing Comments, Q & A

Let’s wrap this up…

Copyright © 2019 Oracle and/or its affiliates. Closing Comments

 Everyone demands quick, time-to-market, scalable, high available and extremely distributed software solutions  There are new standards in place – all flows around JSON  MySQL evolves to a combined SQL + NoSQL solution  Developers gain a new, CRUD based API for both relational and document store development available in most popular programming languages – The X DevAPI  Connector/J is the option for JDBC and the X DevAPI in Java

Copyright © 2019 Oracle and/or its affiliates. Q & A

https://dev.mysql.com

Copyright © 2019 Oracle and/or its affiliates. Safe Harbor

The preceding is intended to outline our general product direction. It is intended for information purposes only, and may not be incorporated into any contract. It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. The development, release, timing, and pricing of any features or functionality described for Oracle’s products may change and remains at the sole discretion of Oracle Corporation.

Statements in this presentation relating to Oracle’s future plans, expectations, beliefs, intentions and prospects are “forward-looking statements” and are subject to material risks and uncertainties. A detailed discussion of these factors and other risks that affect our business is contained in Oracle’s Securities and Exchange Commission (SEC) filings, including our most recent reports on Form 10-K and Form 10-Q under the heading “Risk Factors.” These filings are available on the SEC’s website or on Oracle’s website at http://www.oracle.com/investor. All information in this presentation is current as of September 2019 and Oracle undertakes no duty to update any statement in light of new information or future events.

Copyright © 2019 Oracle and/or its affiliates. Session Survey

Help us make the content even better. Please complete the session survey in the Mobile App.

Copyright © 2019 Oracle and/or its affiliates. Thank You

Filipe Silva Connector/J Developer and Team Lead MySQL Middleware and Clients September 17, 2019

Copyright © 2019 Oracle and/or its affiliates.