Το Heroku παρέχει τη βάση δεδομένων PostgreSQL. Δημιουργήσαμε μια βάση δεδομένων στο Heroku εδώ. Θα δημιουργήσουμε τους πίνακες στη τοπική βάση δεδομένων. Μετά, μπορούμε να κάνουμε export τη βάση και να την κανουμε import στον απομακρυσμένο server στο Heroku.
Για να μπορέσουμε, να χρησιμοποιήσουμε τις βάσεις, χρειάζεται να προσθέσουμε κάποια dependencies στο pom.xml, να προσθέσουμε κάποια properties στο αρχείο application.properties και να δημιουργήσουμε μια κλάση configuration, για να ρυθμίσουμε το JPA.
Προσθέτουμε στο αρχείο pom.xml, τα ακόλουθα dependencies.
<dependency>
<groupId> org.springframework.boot </groupId>
<artifactId< spring-boot-starter-data-jpa </artifactId>
</dependency>
<dependency>
<groupId> org.postgresql </groupId>
<artifactId> postgresql </artifactId>
</dependency>
Προσθέτουμε τα ακόλουθα properties στο αρχείο application.properties. Τα πρώτα 8 περιέχουν ρυθμίσεις για την τοπική και απομακρυσμένη βάση δεδομένων, όπως URL, username και password. Όταν θέλουμε, να τρέξουμε την εφαρμογή τοπικά, πρέπει να κάνουμε comment out τα properties για το Heroku. Αντίστοιχα όταν θέλουμε, να κάνουμε push τις αλλαγές μας στο Heroku, πρέπει να κάνουμε comment out τα properties για το local. Επίσης, παρέχουμε κάποια properties που χρειάζεται το Hibernate και το HikariCP.
#local
spring.datasource.driver-class-name = org.postgresql.Driver
spring.datasource.url = jdbc:postgresql://localhost:5432/postgres
spring.datasource.username = postgres
spring.datasource.password = root
#Heroku
spring.datasource.driver-class-name = org.postgresql.Driver
spring.datasource.url = ${JDBC_DATABASE_URL}
spring.datasource.username = ${JDBC_DATABASE_USERNAME}
spring.datasource.password = ${JDBC_DATABASE_PASSWORD}
spring.jpa.properties.hibernate.hbm2ddl.method = update
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
spring.jpa.properties.hibernate.show_sql = true
spring.jpa.properties.hibernate.format_sql = true
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
spring.datasource.hikari.minimumIdle=2
spring.datasource.hikari.maximumPoolSize=10
spring.datasource.hikari.idleTimeout=300000
spring.datasource.hikari.maxLifetime=1200000
spring.datasource.hikari.connectionTimeout=20000
Θα δημιουργήσουμε μια κλάση JpaConfiguration.java, η οποία θα περιέχει διάφορες ρυθμίσεις για το JPA. Πρώτα, θα κάνουμε ένα καινούριο package springeshop.configuration στο project μας. Στο Spring Tool Suite, πατάμε SpringEshop -> src/main/java, κάνουμε δεξί κλικ -> New -> Package και δίνουμε το όνομα springeshop.configuration . Στο πακέτο αυτό κάνουμε δεξί κλικ -> New -> Class, δίνουμε το όνομα JpaConfiguration και πατάμε finish.
Προσθέτουμε τα ακόλουθα annotations :
@Configuration : Η κλάση περιέχει bean definitions, δηλαδή beans με το annotation @Bean
@EnableJpaRepositories : Είναι annotation, για να ενεργοποιηθούν τα JpaRepositories.
@EnableTransactionManagement : Είναι annotation, για να ενεργοποιηθεί το transaction management.
package springeshop.configuration;
@Configuration
@EnableJpaRepositories(basePackages = "springeshop.repositories",
entityManagerFactoryRef = "entityManagerFactory",
transactionManagerRef = "transactionManager")
@EnableTransactionManagement
public class JpaConfiguration {
Το Datasource Bean είναι ένα εργοστάσιο για τη δημιουργία συνδέσεων με το φυσικό datasource, το οποίο αυτό Datasource αντικειμένο αναπαριστά, δηλαδή την βάση δεδομένων PostgreSQL. Χρειάζεται, να δώσουμε τιμές σε παραμέτρους, όπως το url της βάσης, το username, password και το Jdbc Driver, τις οποίες παίρνουμε από το αρχείο application.properties .
@Autowired
private Environment environment(){
@Bean(name = "dataSource"
public DataSource dataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(environment.getProperty("spring.datasource.driver-class-name"));
dataSource.setUrl(environment.getProperty("spring.datasource.url"));
dataSource.setUsername(environment.getProperty("spring.datasource.username"));
dataSource.setPassword(environment.getProperty("spring.datasource.password"));
return dataSource;
}
Πρέπει να δημιουργήσουμε ένα transaction manager bean, το οποίο ενσωματώνει τον JPA provider, με το transaction management του Spring. Θα χρησιμοποιήσουμε την κλάση JpaTransactionManager, ως τον transaction manager της εφαρμογής.
@Bean
@Autowired
public PlatformTransactionManager transactionManager(EntityManagerFactory emf){
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(emf);
return txManager;
}
Δηλώνουμε ότι θα χρησιμοποιήσουμε το Hibernate ως persistence provider
@Bean
public JpaVendorAdapter jpaVendorAdapter(){
HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
return hibernateJpaVendorAdapter;
}
Δηλώνουμε κάποια συγκεκριμένα properties για το Hibernate.
private Properties jpaProperties(){
Properties properties = new Properties();
properties.put("hibernate.hbm2ddl.method", environment.getRequiredProperty("spring.jpa.properties.hibernate.hbm2ddl.method"));
properties.put("hibernate.show_sql", environment.getRequiredProperty("spring.jpa.properties.hibernate.show_sql"));
properties.put("hibernate.format_sql", environment.getRequiredProperty("spring.jpa.properties.hibernate.format_sql"));
properties.put("hibernate.dialect", environment.getRequiredProperty("spring.jpa.properties.hibernate.dialect"));
properties.put("hibernate.jdbc.lob.non_contextual_creation", environment.getRequiredProperty("spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation"));
return properties;
}
Για να χρησιμοποιήσουμε το JPA, πρέπει να δημιουργήσουμε τον EntityManager. Ο EntityManager παρέχει λειτουργίες πάνω στη βάση, όπως η εύρεση και η αποθήκευση αντικειμένων.
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws NamingException {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(dataSource());
factoryBean.setPackagesToScan(new String[] { "springeshop.model" });
factoryBean.setJpaVendorAdapter(jpaVendorAdapter());
factoryBean.setJpaProperties(jpaProperties());
return factoryBean;