Connetti Java a un database MySQL

Java Top

Ho appena annunciato il nuovo corso Learn Spring , incentrato sui fondamenti di Spring 5 e Spring Boot 2:

>> SCOPRI IL CORSO

1. Panoramica

Ci sono molti modi in cui possiamo connetterci a un database MySQL da Java e in questo tutorial esploreremo diverse opzioni per vedere come ottenere ciò.

Inizieremo esaminando probabilmente le opzioni più popolari utilizzando JDBC e Hibernate.

Quindi, esamineremo anche alcune librerie esterne tra cui MyBatis, Apache Cayenne e Spring Data . Lungo il percorso, forniremo una serie di esempi pratici.

2. Presupposti

Supponiamo di avere già un server MySQL installato e in esecuzione su localhost (porta predefinita 3306) e di avere uno schema di test con la seguente tabella persona:

CREATE TABLE person ( ID INT, FIRST_NAME VARCHAR(100), LAST_NAME VARCHAR(100) );

Avremo anche bisogno dell'artefatto mysql-connector-java che come sempre è disponibile da Maven Central:

 mysql mysql-connector-java 8.0.19 

3. Connessione tramite JDBC

JDBC (Java Database Connectivity) è un'API per la connessione e l'esecuzione di query su un database.

3.1. Proprietà comuni

Nel corso di questo articolo, utilizzeremo in genere diverse proprietà JDBC comuni :

  • URL di connessione: una stringa che il driver JDBC utilizza per connettersi a un database. Può contenere informazioni come dove cercare il database, il nome del database a cui connettersi e altre proprietà di configurazione:
    jdbc:mysql://[host][,failoverhost...] [:port]/[database] [?propertyName1][=propertyValue1] [&propertyName2][=propertyValue2]...

    Imposteremo questa proprietà in questo modo: jdbc: mysql: // localhost: 3306 / test? ServerTimezone = UTC

  • Classe driver: il nome completo della classe del driver da utilizzare. Nel nostro caso, utilizzeremo il driver MySQL: com.mysql.cj.jdbc.Driver
  • Nome utente e password: le credenziali dell'account MySQL

3.2. Esempio di connessione JDBC

Vediamo come possiamo connetterci al nostro database ed eseguire una semplice selezione tutto tramite una prova con più risorse:

String sqlSelectAllPersons = "SELECT * FROM person"; String connectionUrl = "jdbc:mysql://localhost:3306/test?serverTimezone=UTC"; try (Connection conn = DriverManager.getConnection(connectionUrl, "username", "password"); PreparedStatement ps = conn.prepareStatement(sqlSelectAllPersons); ResultSet rs = ps.executeQuery()) { while (rs.next()) { long id = rs.getLong("ID"); String name = rs.getString("FIRST_NAME"); String lastName = rs.getString("LAST_NAME"); // do something with the extracted data... } } catch (SQLException e) { // handle the exception }

Come possiamo vedere, all'interno del corpo try , iteriamo attraverso il set di risultati ed estraiamo i valori dalla tabella person.

4. Connessione tramite ORM

Più tipicamente, ci collegheremo al nostro database MySQL utilizzando un framework ORM (Object Relational Mapping) . Quindi, vediamo alcuni esempi di connessione utilizzando il più popolare di questi framework.

4.1. API Hibernate native

In questa sezione vedremo come utilizzare Hibernate per gestire una connessione JDBC al nostro database.

Innanzitutto, dobbiamo aggiungere la dipendenza Maven hibernate-core :

 org.hibernate hibernate-core 5.4.10.Final 

Hibernate richiede la creazione di una classe entità per ogni tabella. Andiamo avanti e definiamo la classe Person :

@Entity @Table(name = "Person") public class Person { @Id Long id; @Column(name = "FIRST_NAME") String firstName; @Column(name = "LAST_NAME") String lastName; // getters & setters } 

Un altro aspetto essenziale è creare il file di risorse Hibernate, tipicamente denominato hibernate.cfg.xml , dove definiremo le informazioni di configurazione:

     com.mysql.cj.jdbc.Driver jdbc:mysql://localhost:3306/test?serverTimezone=UTC username password  org.hibernate.dialect.MySQL5Dialect  validate    

Hibernate ha molte proprietà di configurazione. Oltre alle proprietà di connessione standard, vale la pena menzionare la proprietà dialect che ci consente di specificare il nome del dialetto SQL per il database.

Questa proprietà viene utilizzata dal framework per convertire correttamente le istruzioni Hibernate Query Language (HQL) nell'SQL appropriato per il nostro database. Hibernate viene fornito con più di 40 dialetti SQL. Dato che ci stiamo concentrando su MySQL in questo articolo, ci atterremo al dialetto MySQL5Dialect .

Infine, Hibernate deve anche conoscere il nome completo della classe entità tramite il tag di mappatura. Una volta completata la configurazione, utilizzeremo la classe SessionFactory , che è la classe responsabile della creazione e del pool di connessioni JDBC.

In genere, questo deve essere impostato solo una volta per un'applicazione:

SessionFactory sessionFactory; // configures settings from hibernate.cfg.xml StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure().build(); try { sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory(); } catch (Exception e) { // handle the exception }

Ora che abbiamo configurato la nostra connessione, possiamo eseguire una query per selezionare tutte le persone dalla nostra tabella persona:

Session session = sessionFactory.openSession(); session.beginTransaction(); List result = session.createQuery("from Person", Person.class).list(); result.forEach(person -> { //do something with Person instance... }); session.getTransaction().commit(); session.close();

4.2. MyBatis

MyBatis è stato introdotto nel 2010 ed è un framework SQL mapper con la semplicità come punto di forza . In un altro tutorial, abbiamo parlato di come integrare MyBatis con Spring e Spring Boot. Qui ci concentreremo su come configurare MyBatis direttamente.

Per usarlo, dobbiamo aggiungere la dipendenza mybatis :

 org.mybatis mybatis 3.5.3 

Supponendo di riutilizzare la classe Person sopra senza annotazioni, possiamo procedere alla creazione di un'interfaccia PersonMapper :

public interface PersonMapper { String selectAll = "SELECT * FROM Person"; @Select(selectAll) @Results(value = { @Result(property = "id", column = "ID"), @Result(property = "firstName", column = "FIRST_NAME"), @Result(property = "lastName", column = "LAST_NAME") }) List selectAll(); }

Il passaggio successivo riguarda la configurazione di MyBatis:

Configuration initMybatis() throws SQLException { DataSource dataSource = getDataSource(); TransactionFactory trxFactory = new JdbcTransactionFactory(); Environment env = new Environment("dev", trxFactory, dataSource); Configuration config = new Configuration(env); TypeAliasRegistry aliases = config.getTypeAliasRegistry(); aliases.registerAlias("person", Person.class); config.addMapper(PersonMapper.class); return config; } DataSource getDataSource() throws SQLException { MysqlDataSource dataSource = new MysqlDataSource(); dataSource.setDatabaseName("test"); dataSource.setServerName("localhost"); dataSource.setPort(3306); dataSource.setUser("username"); dataSource.setPassword("password"); dataSource.setServerTimezone("UTC"); return dataSource; }

The configuration consists of creating a Configuration object which is a container for settings such as the Environment. It also contains the data source settings.

We can then use the Configuration object, which is normally set up once for an application to create a SqlSessionFactory:

Configuration configuration = initMybatis(); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration); try (SqlSession session = sqlSessionFactory.openSession()) { PersonMapper mapper = session.getMapper(PersonMapper.class); List persons = mapper.selectAll(); // do something with persons list ... }

4.3. Apache Cayenne

Apache Cayenne is a persistence framework whose first release dates back to 2002. To learn more about it, we suggest reading our introduction to Apache Cayenne.

As usual, let's add the cayenne-server Maven dependency:

 org.apache.cayenne cayenne-server 4.0.2 

We're going to specifically focus on the MySQL connection settings. In this case, we'll configure the cayenne-project.xml:

After the automatic generation of the datamap.map.xml and Person class in the form of a CayenneDataObject, we can execute some queries.

For example, we'll continue as previously with a select all:

ServerRuntime cayenneRuntime = ServerRuntime.builder() .addConfig("cayenne-project.xml") .build(); ObjectContext context = cayenneRuntime.newContext(); List persons = ObjectSelect.query(Person.class).select(context); // do something with persons list...

5.Connecting Using Spring Data

Spring Data is a Spring-based programming model for data access. Technically, Spring Data is an umbrella project which contains many subprojects that are specific to a given database.

Let's see how to use two of these projects to connect to a MySQL database.

5.1. Spring Data / JPA

Spring Data JPA is a robust framework that helps reduce boilerplate code and provides a mechanism for implementing basic CRUD operations via one of several predefined repository interfaces. In addition to this, it has many other useful features.

Be sure to check out our introduction to Spring Data JPA to learn more.

The spring-data-jpa artifact can be found on Maven Central:

 org.springframework.data spring-data-jpa 2.2.4.RELEASE 

We'll continue using the Person class. The next step is to configure JPA using annotations:

@Configuration @EnableJpaRepositories("packages.to.scan") public class JpaConfiguration { @Bean public DataSource dataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/test?serverTimezone=UTC"); dataSource.setUsername( "username" ); dataSource.setPassword( "password" ); return dataSource; } @Bean public JpaTransactionManager transactionManager(EntityManagerFactory emf) { return new JpaTransactionManager(emf); } @Bean public JpaVendorAdapter jpaVendorAdapter() { HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter(); jpaVendorAdapter.setDatabase(Database.MYSQL); jpaVendorAdapter.setGenerateDdl(true); return jpaVendorAdapter; } @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() { LocalContainerEntityManagerFactoryBean lemfb = new LocalContainerEntityManagerFactoryBean(); lemfb.setDataSource(dataSource()); lemfb.setJpaVendorAdapter(jpaVendorAdapter()); lemfb.setPackagesToScan("packages.containing.entity.classes"); return lemfb; } }

To allow Spring Data to implement the CRUD operations, we have to create an interface that extends the CrudRepository interface:

@Repository public interface PersonRepository extends CrudRepository { }

And finally, let's see an example of select-all with Spring Data:

personRepository.findAll().forEach(person -> { // do something with the extracted person });

5.2. Spring Data / JDBC

Spring Data JDBC is a limited implementation of the Spring Data family, with its primary goal to allow simple access to relational databases.

For this reason, it doesn't provide features like caching, dirty tracking, lazy loading, and many other JPA features.

This time the Maven dependency we need is spring-data-jdbc:

 org.springframework.data spring-data-jdbc 1.1.4.RELEASE 

The configuration is lighter compared to the one we used in the previous section for Spring Data JPA:

@Configuration @EnableJdbcRepositories("packages.to.scan") public class JdbcConfiguration extends AbstractJdbcConfiguration { // NamedParameterJdbcOperations is used internally to submit SQL statements to the database @Bean NamedParameterJdbcOperations operations() { return new NamedParameterJdbcTemplate(dataSource()); } @Bean PlatformTransactionManager transactionManager() { return new DataSourceTransactionManager(dataSource()); } @Bean public DataSource dataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/test?serverTimezone=UTC"); dataSource.setUsername("username"); dataSource.setPassword("password"); return dataSource; } }

In the case of Spring Data JDBC, we have to define a new Person class or modify the existing one to add some Spring specific annotations.

This is because Spring Data JDBC will take care directly of the entity mapping instead of Hibernate:

import org.springframework.data.annotation.Id; import org.springframework.data.relational.core.mapping.Column; import org.springframework.data.relational.core.mapping.Table; @Table(value = "Person") public class Person { @Id Long id; @Column(value = "FIRST_NAME") String firstName; @Column(value = "LAST_NAME") String lastName; // getters and setters }

Con Spring Data JDBC, possiamo anche utilizzare l' interfaccia CrudRepository . Quindi la dichiarazione sarà identica a quella che abbiamo scritto sopra nell'esempio JPA Spring Data. Allo stesso modo, lo stesso vale per l'esempio Seleziona tutto.

6. Conclusione

In questo tutorial, abbiamo visto diversi modi per connettersi a un database MySQL da Java . Abbiamo iniziato con la connessione JDBC essenziale. Quindi abbiamo esaminato gli ORM comunemente usati come Hibernate, Mybatis e Apache Cayenne. Infine, abbiamo esaminato Spring Data JPA e Spring Data JDBC.

L'utilizzo di API JDBC o Hibernate significa più codice boilerplate. L'utilizzo di framework robusti, come Spring Data o Mybatis, richiede una maggiore configurazione ma offre un vantaggio significativo perché fornisce implementazioni predefinite e funzionalità come il caching e il caricamento lento.

Fondo Java

Ho appena annunciato il nuovo corso Learn Spring , incentrato sui fondamenti di Spring 5 e Spring Boot 2:

>> SCOPRI IL CORSO