Току що обявих новия курс Learn Spring , фокусиран върху основите на Spring 5 и Spring Boot 2:
>> ПРЕГЛЕД НА КУРСА1. Общ преглед
Има много начини да се свържем с MySQL база данни от Java и в този урок ще проучим няколко опции, за да видим как да постигнем това.
Ще започнем с разглеждането на може би най-популярните опции, използващи JDBC и Hibernate.
След това ще разгледаме и някои външни библиотеки, включително MyBatis, Apache Cayenne и Spring Data . По пътя ще предоставим редица практически примери.
2. Предпоставки
Ще приемем, че вече имаме инсталиран и работещ MySQL сървър на localhost (порт по подразбиране 3306) и че имаме тестова схема със следната таблица на човека:
CREATE TABLE person ( ID INT, FIRST_NAME VARCHAR(100), LAST_NAME VARCHAR(100) );
Ще ни трябва и артефактът mysql-connector-java , който както винаги е достъпен от Maven Central:
mysql mysql-connector-java 8.0.19
3. Свързване чрез JDBC
JDBC (Java Database Connectivity) е API за свързване и изпълнение на заявки в база данни.
3.1. Общи свойства
По време на тази статия обикновено ще използваме няколко често срещани JDBC свойства :
- URL за връзка - низ, който JDBC драйверът използва за свързване към база данни. Той може да съдържа информация като къде да търсите базата данни, името на базата данни, към която да се свържете и други свойства на конфигурацията:
jdbc:mysql://[host][,failoverhost...] [:port]/[database] [?propertyName1][=propertyValue1] [&propertyName2][=propertyValue2]...
Ще зададем това свойство така: jdbc: mysql: // localhost: 3306 / test? ServerTimezone = UTC
- Клас на водача - пълното име на класа на драйвера, който да използвате. В нашия случай ще използваме драйвера на MySQL: com.mysql.cj.jdbc.Driver
- Потребителско име и парола - идентификационните данни на акаунта в MySQL
3.2. Пример за JDBC връзка
Нека да видим как можем да се свържем с нашата база данни и да изпълним прост избор на всички чрез опит с множество ресурси:
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 }
Както можем да видим, вътре в тялото за опит ние прелистваме резултата и извличаме стойностите от таблицата на човека.
4. Свързване чрез ORM
По-обикновено ще се свържем с нашата база данни MySQL, като използваме рамка за релационно картографиране на обекти (ORM) . Така че, нека да видим някои примери за свързване, използвайки по-популярните от тези рамки.
4.1. Природни API на Hibernate
В този раздел ще видим как да използваме Hibernate за управление на JDBC връзка с нашата база данни.
Първо, трябва да добавим зависимостта на Maven със зимен сън :
org.hibernate hibernate-core 5.4.10.Final
Хибернацията изисква да се създаде клас на обект за всяка таблица. Нека да продължим напред и да определим класа 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 }
Друг съществен аспект е създаването на ресурсен файл Hibernate, обикновено наречен hibernate.cfg.xml , където ще дефинираме информация за конфигурацията:
com.mysql.cj.jdbc.Driver jdbc:mysql://localhost:3306/test?serverTimezone=UTC username password org.hibernate.dialect.MySQL5Dialect validate
Hibernate има много конфигурационни свойства. Освен стандартните свойства на свързване, заслужава да се спомене свойството dialect, което ни позволява да посочим името на SQL диалекта за базата данни.
Това свойство се използва от рамката, за да преобразува правилно изразите на Hibernate Query Language (HQL) в подходящия SQL за дадената ни база данни. Хибернацията се доставя с повече от 40 SQL диалекта. Тъй като се фокусираме върху MySQL в тази статия, ще се придържаме към диалекта MySQL5Dialect .
И накрая, Hibernate също трябва да знае пълното име на класа на обекта чрез маркера за картографиране. След като завършим конфигурацията, ще използваме класа SessionFactory , който е класът, отговорен за създаването и обединяването на JDBC връзки.
Обикновено това трябва да се настрои само веднъж за приложение:
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 }
Сега, когато сме настроили връзката си, можем да изпълним заявка, за да изберем всички хора от нашата таблица с хора:
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 е представен през 2010 г. и представлява рамка на SQL mapper, чиято сила е простотата . В друг урок говорихме за това как да интегрираме MyBatis с Spring и Spring Boot. Тук ще се съсредоточим върху това как да конфигурираме MyBatis директно.
За да го използваме, трябва да добавим зависимостта mybatis :
org.mybatis mybatis 3.5.3
Ако приемем, че използваме повторно класа Person по-горе без пояснения, можем да продължим да създаваме интерфейс 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(); }
Следващата стъпка е всичко за конфигурацията 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 }
С Spring Data JDBC можем да използваме и интерфейса CrudRepository . Така декларацията ще бъде идентична с тази, която написахме по-горе в примера Spring JPA. По същия начин същото важи и за примера за всички избрани.
6. Заключение
В този урок видяхме няколко различни начина за свързване към база данни MySQL от Java . Започнахме с основната JDBC връзка. След това разгледахме често използвани ORM като Hibernate, Mybatis и Apache Cayenne. Накрая разгледахме Spring Data JPA и Spring Data JDBC.
Използването на JDBC или Hibernate API означава повече шаблонни кодове. Използването на здрави рамки, като Spring Data или Mybatis, изискват повече конфигурация, но дават значително предимство, тъй като осигуряват реализации по подразбиране и функции като кеширане и мързеливо зареждане.
Дъно на Java