Convidamos futuros alunos do curso "Java Developer. Professional" e todos os interessados a participar da aula aberta sobre o tema "Introdução ao Spring Data Jdbc" .
E agora estamos compartilhando a tradução tradicional de material útil.
Este artigo fornece uma visão geral de bibliotecas e APIs populares para trabalhar com bancos de dados em Java, incluindo JDBC, Hibernate, JPA, jOOQ, Spring Data e muito mais.
Java e bancos de dados: uma introdução
Cada vez que você precisa interagir com bancos de dados, surgem três perguntas:
Qual abordagem de desenvolvimento deve ser usada: java-first ou database-first? Escreva classes Java ou consultas SQL primeiro? O banco de dados existente será usado?
SQL-: CRUD- (select from, insert into, update where), ?
- (object-relational mapping, ORM)? Java / ?
- :
public class User {
private Integer id;
private String firstName;
private String lastName;
// Constructor/Getters/Setters....
}
USERS, :
id |
first_name |
last_name |
1 |
hansi |
huber |
2 |
max |
mutzke |
3 |
donald |
trump |
Java- ?
:
JDBC — .
SQL-, jOOQ Spring JDBC.
-
, JDBC. ? , Spring Hibernate, JDBC.
JDBC:
JDBC?
Java — JDBC API (Java Database Connectivity). , , JDBC . , , SQL-, JDBC .
JDBC , , JDBC JDK / JRE. JDBC- .
, JDBC, , SQL-, What is JDBC? (" JDBC?") .
JDBC
, Users, , , , List<User>
— Java.
: JDBC SQL Java- ( ). :
package com.marcobehler;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class JdbcQueries {
public static void main(String[] args) throws SQLException {
try (Connection conn = DriverManager
.getConnection("jdbc:mysql://localhost/test?serverTimezone=UTC",
"myUsername", "myPassword")) {
PreparedStatement selectStatement = conn.prepareStatement("select * from users");
ResultSet rs = selectStatement.executeQuery();
List<User> users = new ArrayList<>();
while (rs.next()) { // will traverse through all rows
Integer id = rs.getInt("id");
String firstName = rs.getString("first_name");
String lastName = rs.getString("last_name");
User user = new User(id, firstName, lastName);
users.add(user);
}
}
}
}
:
try (Connection conn = DriverManager
.getConnection("jdbc:mysql://localhost/test?serverTimezone=UTC",
"myUsername", "myPassword")) {
MySQL. DriverManager.getConnection
try-with-resources, , .
PreparedStatement selectStatement = conn.prepareStatement("select * from users");
ResultSet rs = selectStatement.executeQuery();
SQL- PreparedStatement
. (PreparedStatement
?
, .)
List<User> users = new ArrayList<>();
while (rs.next()) { // will traverse through all rows
Integer id = rs.getInt("id");
String firstName = rs.getString("first_name");
String lastName = rs.getString("last_name");
User user = new User(id, firstName, lastName);
users.add(user);
}
ResultSet
( , SQL-), Java, ResultSet
(getString()
, getInt()
).
( ) :
SQL- (:
select * from USERS where name = ? and registration_date = ?
). SQL-.
, , .
, JDBC : SQL Java .
JDBC
JDBC " ". SQL JDBC, SQL- Java. .
, .
ORM-: Hibernate, JPA
Java-, , Java, SQL. java-first, , Java-, .
, , - : Java- ( )? Java- ( , ).
Hibernate?
Hibernate — ORM- (Object-Relational Mapping, - ), 2001 (!). 5.4.X, 6.x .
Hibernate , :
() java- - , .
SQL- CRUD-, , .
(HQL, Criteria API) SQL. , "-" SQL.
, . , , , , , JDBC.
create table users (
id integer not null,
first_name varchar(255),
last_name varchar(255),
primary key (id)
)
Java.
public class User {
private Integer id;
private String firstName;
private String lastName;
//Getters and setters are omitted for brevity
}
, hibernate-core.jar . Hibernate, User.java
Users? Hibernate.
Hibernate
Hibernate , . User.java
Invoices () Users ()?
xml-. xml-, .
, @Entity, @Column @Table. , User.java
, , .
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.GeneratedValue;
import javax.persistence.Column;
import javax.persistence.Id;
@Entity
@Table(name="users")
public static class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@Column(name="first_name")
private String firstName;
@Column(name="last_name")
private String lastName;
//Getters and setters are omitted for brevity
}
, :
@Entity — Hibernate, .
@Table — Hibernate, .
@Column — Hibernate, .
@Id @GeneratedValue — Hibernate, .
, , . Hibernate , .
Hibernate (5.x)
Hibernate. , Hibernate, SessionFactory
, .
SessionFactory
Session
. Session, , ( , JDBC-) . Session SQL / HQL / Criteria — .
Hibernate.
Hibernate (> 5.x) , Spring . Hibernate, .
public static void main(String[] args) {
// Hibernate specific configuration class
StandardServiceRegistryBuilder standardRegistry
= new StandardServiceRegistryBuilder()
.configure()
.build();
// Here we tell Hibernate that we annotated our User class
MetadataSources sources = new MetadataSources( standardRegistry );
sources.addAnnotatedClass( User.class );
Metadata metadata = metadataSources.buildMetadata();
// This is what we want, a SessionFactory!
SessionFactory sessionFactory = metadata.buildSessionFactory();
}
Hibernate
, SessionFactory
, Session
(, ) SessionFactory
, , , .
Hibernate / JPA "persistence" (, ), Java . , , : , .. SQL INSERT ().
, SQL : Hibernate .
Session session = sessionFactory.openSession();
User user = new User();
user.setFirstName("Hans");
user.setLastName("Dampf");
// this line will generate and execute the "insert into users" sql for you!
session.save( user );
JDBC PreparedStatement
, Hibernate , SQL ( !).
, SQL- (select
, update
delete
).
// Hibernate generates: "select from users where id = 1"
User user = session.get( User.class, 1 );
// Hibernate generates: "update users set...where id=1"
session.update(user);
// Hibernate generates: "delete from useres where id=1"
session.delete(user);
Hibernate Query Language (HQL)
, User
. , SQL-. Hibernate , HQL (Hibernate Query Language).
HQL SQL, Java- . , HQL- (MySQL, Oracle, Postgres . .), , .
, "HQL Java-"? :
List<User> users = session.createQuery("select from User u where u.firstName = 'hans'", User.class).list();
session.createQuery("update User u set u.lastName = :newName where u.lastName = :oldName")
.executeUpdate();
SQL-, , (first_name
), (u.firstName
) User.java
! Hibernate HQL SQL . SELECT User.
HQL HQL Hibernate.
Criteria API
HQL- , , ( IDE, IntelliJ). — HQL / SQL ( WHERE ).
Hibernate — Criteria API. Criteria API (1 2), . 1 - Hibernate 6.x, , 2.
Criteria API (v2) . " " . .
, HQL Criteria API.
CriteriaBuilder builder = entityManager.getCriteriaBuilder(); CriteriaQuery<User> criteria = builder.createQuery( User.class ); Root<User> root = criteria.from( User.class ); criteria.select( root ); criteria.where( builder.equal( root.get( User_.firstName ), "hans" ) ); List<User> users = entityManager.createQuery( criteria ).getResultList();
, . , if-else
where
.
, "select * from users where firstName =?
" .
Hibernate
Hibernate , . . Hibernate : , (lazy load), . , - .
:
, "Hibernate - , " - . , , Hibernate.
, Hibernate SQL. , , SQL Hibernate' SQL- .
: Hibernate SQL.
Hibernate?
"Java Persistence with Hibernate". 608 , Hibernate. Hibernate.
, (Vlad Mihalcea) (Thorben Janssen). Hibernate .
, Hibernate . , Hibernate.
Java Persistence API (JPA)?
Hibernate, JPA? Hibernate?
JPA — , . JPA , , JPA. JPA, , Hibernate, EclipseLink TopLink.
, , , , (, Criteria API . .) ., JPA-.
, , Hibernate EclipseLink, JPA- . JPA- (Hibernate) , . , JPA — Hibernate.
JPA
JPA 1.0 — 2006 .
JPA 2.0 — 2009 .
JPA 2.1 — 2013 .
JPA 2.2 — 2017 .
, , Vlad Mihalcea Thorben Janssen .
Hibernate JPA?
JPA , persistance- (Hibernate, EclipseLink ..) .
JPA Hibernate, JPA Hibernate. , JPQL — HQL . JPQL HQL, .
, JPA , — , , , , Hibernate. Hibernate, EclipseLink TopLink .
: JPA Hibernate?
, , :
JPA Hibernate- , JPA.
Hibernate ( ).
JPA
JPA , , EntityManagerFactory
, EntityManager
.
, JDBC Hibernate API. JPA API.
EntityManagerFactory factory = Persistence.createEntityManagerFactory( "org.hibernate.tutorial.jpa" );
EntityManager entityManager = factory.createEntityManager();
entityManager.getTransaction().begin();
entityManager.persist( new User( "John Wayne") );
entityManager.persist( new User( "John Snow" ) );
entityManager.getTransaction().commit();
entityManager.close();
(persist save, EntityManager Session), , Hibernate.
Hibernate, :
package org.hibernate;
public interface Session extends SharedSessionContract, EntityManager, HibernateEntityManager, AutoCloseable {
// methods
}
// and
public interface SessionFactory extends EntityManagerFactory, HibernateEntityManagerFactory, Referenceable, Serializable, java.io.Closeable {
// methods
}
:
Hibernate SessionFactory — JPA EntityManagerFactory
Hibernate Session — JPA EntityManager
.
JPQL
, JPA — JPQL. , HQL (Hibernate), JPQL HQL, .
, :
// HQL
int updatedEntities = session.createQuery(
"update Person " +
"set name = :newName " +
"where name = :oldName" )
.setParameter( "oldName", oldName )
.setParameter( "newName", newName )
.executeUpdate();
// JPQL
int updatedEntities = entityManager.createQuery(
"update Person p " +
"set p.name = :newName " +
"where p.name = :oldName" )
.setParameter( "oldName", oldName )
.setParameter( "newName", newName )
.executeUpdate();
Criteria API JPA
HQL JPQL, Criteria API JPA Criteria API Hibernate. Criteria API Hibernate .
JPA?
JPA , Hibernate. EclipseLink (. Hibernate vs Eclipselink) ( ) TopLink.
Hibernate , . , BatooJPA. , JPA .
, , , . Hibernate, , 2020 .
QueryDSL
, QueryDSL, JPA? HQL / JPQL (.. ), Criteria API (2.0).
QueryDSL : Criteria API, .
, QueryDSL - , 2020 , . JPQ, NoSQL , MongoDB Lucene.
QueryDSL, SQL "select * from users where first_name =: name"
QUser user = QUser.user;
JPAQuery<?> query = new JPAQuery<Void>(entityManager);
List<User> users = query.select(user)
.from(user)
.where(user.firstName.eq("Hans"))
.fetch();
QUser
? QueryDSL User
, JPA / Hibernate, , .
. JPA Criteria 2.0?
ORM- Java:
ORM- — . — , - JPA SQL.
, , ORM . , , .
, , Hibernate, SQL .
SQL-:
, , , (database-first), ORM, Java (java-first).
, () Java-.
jOOQ
jOOQ — (Lukas Eder). , SQL, Java.
, jOOQ :
Java, , jOOQ.
SQL- JDBC .
jOOQ SQL, .
, , jOOQ Users, . jOOQ USERS , :
// "select u.first_name, u.last_name, s.id from USERS u inner join SUBSCRIPTIONS s
// on u.id = s.user_id where u.first_name = :name"
Result<Record3<String, String, String>> result =
create.select(USERS.FIRST_NAME, USERS.LAST_NAME, SUBSCRIPTIONS.ID)
.from(USERS)
.join(SUBSCRIPTIONS)
.on(USERS.SUBSCRIPTION_ID.eq(SUBSCRIPTIONS.ID))
.where(USERS.FIRST_NAME.eq("Hans"))
.fetch();
jOOQ SQL- , CRUD-, POJO .
( , pivot, flashback-, OLAP, , ).
jOOQ.
MyBatis
MyBatis — database-first. MyBatis — IBATIS 3.0, Apache Attic.
MyBatis SQLSessionFactory ( SessionFactory Hibernate). SQLSessionFactory SQL- . SQL- XML, .
:
package org.mybatis.example;
public interface UserMapper {
@Select("SELECT * FROM users WHERE id = #{id}")
User selectUser(int id);
}
XML-:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.mybatis.example.UserMapper">
<select id="selectUser" resultType="User">
select * from users where id = #{id}
</select>
</mapper>
:
UserMapper mapper = session.getMapper(UserMapper.class);
User user = mapper.selectUser(1);
MyBatis , User. , , , . XML- .
MyBatis SQL, , , XML SQL- (- if-else-when SQL-).
Jdbi
Jdbi — JDBC, . SQL-. API .
-, Fluent API:
Jdbi jdbi = Jdbi.create("jdbc:h2:mem:test"); // (H2 in-memory database)
List<User> users = jdbi.withHandle(handle -> {
handle.execute("CREATE TABLE user (id INTEGER PRIMARY KEY, name VARCHAR)");
// Named parameters from bean properties
handle.createUpdate("INSERT INTO user(id, name) VALUES (:id, :name)")
.bindBean(new User(3, "David"))
.execute();
// Easy mapping to any type
return handle.createQuery("SELECT * FROM user ORDER BY name")
.mapToBean(User.class)
.list();
});
-, API:
// Define your own declarative interface
public interface UserDao {
@SqlUpdate("CREATE TABLE user (id INTEGER PRIMARY KEY, name VARCHAR)")
void createTable();
@SqlUpdate("INSERT INTO user(id, name) VALUES (:id, :name)")
void insertBean(@BindBean User user);
@SqlQuery("SELECT * FROM user ORDER BY name")
@RegisterBeanMapper(User.class)
List<User> listUsers();
}
public class MyApp {
public static void main(String[] args) {
Jdbi jdbi = Jdbi.create("jdbc:h2:mem:test");
jdbi.installPlugin(new SqlObjectPlugin());
List<User> userNames = jdbi.withExtension(UserDao.class, dao -> {
dao.createTable();
dao.insertBean(new User(3, "David"));
return dao.listUsers();
});
}
}
fluent-jdbc
fluent-jdbc — , Jdbi. JDBC. .
FluentJdbc fluentJdbc = new FluentJdbcBuilder()
.connectionProvider(dataSource)
.build();
Query query = fluentJdbc.query();
query
.update("UPDATE CUSTOMER SET NAME = ?, ADDRESS = ?")
.params("John Doe", "Dallas")
.run();
List<Customer> customers = query.select("SELECT * FROM CUSTOMER WHERE NAME = ?")
.params("John Doe")
.listResult(customerMapper);
SimpleFlatMapper
SimpleFlatMapper , , ResultSet JDBC Record jOOQ POJO. , " " , , JDBC, jOOQ, queryDSL, JDBI Spring JDBC.
JDBC:
// will map the resultset to User POJOs
JdbcMapper<DbObject> userMapper =
JdbcMapperFactory
.newInstance()
.newMapper(User.class)
try (PreparedStatement ps = con.prepareStatement("select * from USERS")) {
ResultSet rs = ps.executeQuery());
userMapper.forEach(rs, System.out::println); //prints out all user pojos
}
Spring JDBC Spring Data
Spring , Spring Data, Spring.
Spring JDBC Template
JDBCTemplate
— Spring (, spring-jdbc). 2001 , Spring Data JDBC.
JDBC- ResultSet, , , @Transactional- Spring.
: JdbcTemplate
NamedParameterJdbcTemplate
. , , .
// plain JDBC template with ? parameters
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.execute("CREATE TABLE users(" +
"id SERIAL, first_name VARCHAR(255), last_name VARCHAR(255))"); (1)
jdbcTemplate.batchUpdate("INSERT INTO users(first_name, last_name) VALUES (?,?)", Arrays.asList("john", "wayne")); (2)
jdbcTemplate.query(
"SELECT id, first_name, last_name FROM users WHERE first_name = ?", new Object[] { "Josh" },
(rs, rowNum) -> new User(rs.getLong("id"), rs.getString("first_name"), rs.getString("last_name"))
).forEach(user -> log.info(user.toString())); (3)
// named JDBC template with :named parameters
NamedParameterJdbcTemplate namedTemplate = new NamedParameterJdbcTemplate(datasource);
SqlParameterSource namedParameters = new MapSqlParameterSource().addValue("id", 1);
namedParameterJdbcTemplate.queryForObject( (4)
"SELECT * FROM USERS WHERE ID = :id", namedParameters, String.class);
SQL . , JDBC SQLException, Spring
RuntimeException
.
(
?
) .
RowMapper
JDBC ResultSet POJO .
NamedParameterJdbcTemplate
SQL- (,:id
), (?
).
, , JdbcTemplate
JDBC API.
Spring
Spring — @Transactional.
, , , Hibernate, jOOQ JPA, .
JPA, EntityManager (, EntityManager — Hibernate Session, JDBC ).
EntityManagerFactory factory = Persistence.createEntityManagerFactory( "org.hibernate.tutorial.jpa" );
EntityManager entityManager = factory.createEntityManager();
entityManager.getTransaction().begin();
entityManager.persist( new Event( "Our very first event!", new Date() ) );
entityManager.persist( new Event( "A follow up event", new Date() ) );
entityManager.getTransaction().commit();
entityManager.close();
Spring Hibernate / JPA :
@PersistenceContext
private EntityManager entityManager;
@Transactional
public void doSomeBusinessLogic() {
entityManager.persist( new Event( "Our very first event!", new Date() ) );
entityManager.persist( new Event( "A follow up event", new Date() ) );
}
, . , , .
, Java Database Connections & Transactions (" Java"). , .
Spring Data JPA
, Spring Data, " Spring , ". , Fortune 500. ?
, : Spring Data JDBC Spring Data JPA.
, Spring Data REST, Spring Data Redis Spring Data LDAP. -.
Spring Data JDBC Spring Data JPA?
Spring Data /DAO SQL-. ( , .)
: — /DAO .
User.java
, UserRepository
. UserRepository
, findByEmail
, findById
. . , SQL- Users.
User user = userRepository.findByEmail("my@email.com")
Spring Data , JPA- User (@Entity, @Column, @Table ..) ! , CRUD- (save, delete, findBy) .
Spring Data JPA-
. , classpath
spring-data-{jdbc|jpa}.jar
. :
import org.springframework.data.jpa.repository.JpaRepository;
import com.marcobehler.domain.User;
public interface MyUserRepository extends JpaRepository<User, Long> {
// JpaRepository contains all of these methods, you do not have to write them yourself!
List<T> findAll();
List<T> findAll(Sort sort);
List<T> findAllById(Iterable<ID> ids);
<S extends T> List<S> saveAll(Iterable<S> entities);
// and many more...that you can execute without implementing, because Spring Data JPA will
// automatically generate an implementation for you - at runtime
}
JpaRepository
Spring Data ( , JPA), find
/save
( ), JpaRepository
( ).
Spring Data JPA / JDBC
, JPA ( SQL), . , , Ruby on Rails.
import org.springframework.data.jpa.repository.JpaRepository;
import com.marcobehler.domain.User;
public interface MyUserRepository extends JpaRepository<User, Long> {
List<User> findByEmailAddressAndLastname(String emailAddress, String lastname);
}
Spring . SQL: "select * from Users where email_address = :emailAddress and lastName = :lastName
".
Spring Data JDBC ( CrudRepository
). .
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.jdbc.repository.Query;
import com.marcobehler.domain.User;
public interface MyUserRepository extends CrudRepository<User, Long> {
@Query("select * from Users where email = :emailAddress and lastName = :lastName ")
List<User> findByEmailAddressAndLastname(@Param("emailAddress") String emailAddress, @Param("lastName") String lastname);
}
Spring Data JPA ( @Query , ). - .
import org.springframework.data.jpa.repository.Query;
public interface MyUserRepository extends JpaRepository<User, Long> {
@Query("select u from User u where u.emailAddress = ?1")
User findByEmailAddress(String emailAddress);
}
Spring Data:
:
Spring Data — , , . javax.persistence DAO.
Spring Data JPA — JPA / Hibernate. , , , . Spring Data JPA - JPA-, ORM.
Spring Data JDBC — JDBC. JDBC, ORM (, , …). .
, Spring Data Spring- Spring Boot-.
. . ( , , , ):
, , , SQL ( java-).
, .
, .. 608 .
Hibernate, Hibernate, JPA.
jOOQ database-first .
. , JPA- jOOQ JDBC. , QueryDSL.
"Java Developer. Professional".
" Spring Data Jdbc".
