Hibernate e SQLite possono essere utilizzati insieme per creare applicazioni Java leggere, prototipi, tool desktop, applicazioni locali, test di persistenza o piccoli sistemi che devono salvare dati in un database relazionale contenuto in un singolo file.

SQLite è un database molto particolare rispetto a MySQL, PostgreSQL, Oracle o SQL Server. Non richiede un server separato, non necessita di installazione complessa e salva l’intero database in un file. Questo lo rende molto comodo per progetti semplici, applicazioni monoutente, prototipi, ambienti di test e piccoli strumenti standalone.

Hibernate, invece, è un framework ORM per Java che permette di mappare entità Java su tabelle relazionali. Attraverso JPA o API native di Hibernate, possiamo lavorare con classi, oggetti e relazioni invece di scrivere manualmente tutto il codice SQL.

L’integrazione tra Hibernate e SQLite richiede due elementi fondamentali:

  • un driver JDBC per SQLite;
  • un dialect Hibernate compatibile con SQLite.

In breve: per usare SQLite con Hibernate moderno servono il driver org.xerial:sqlite-jdbc e il dialect org.hibernate.community.dialect.SQLiteDialect, disponibile nel modulo hibernate-community-dialects.

Indice dei contenuti

Cos’è SQLite

SQLite è un DBMS relazionale embedded. A differenza di database come PostgreSQL o MySQL, non richiede un processo server separato. Il database è salvato in un normale file sul filesystem.

Un URL JDBC SQLite può essere semplice come:

jdbc:sqlite:university.sqlite

In questo caso il database viene salvato nel file:

university.sqlite

SQLite è molto usato in:

  • applicazioni desktop;
  • applicazioni mobile;
  • tool locali;
  • prototipi;
  • test automatici;
  • applicazioni monoutente;
  • piccoli sistemi embedded;
  • script e utility Java.

Caratteristiche principali

  • database contenuto in un singolo file;
  • nessun server da installare;
  • configurazione molto semplice;
  • buona affidabilità per scenari locali;
  • supporto SQL sufficiente per molti casi d’uso;
  • adatto a piccoli dataset e applicazioni leggere;
  • non ideale per alta concorrenza in scrittura.

Concetto chiave: SQLite è leggero e pratico, ma non deve essere scelto automaticamente per ogni applicazione. È perfetto per alcuni scenari, meno adatto per altri.

Quando usare SQLite con Hibernate

Usare Hibernate con SQLite può avere senso quando vuoi sfruttare il modello ORM di Hibernate ma non hai bisogno di un database server completo.

Casi in cui può essere una buona scelta

  • applicazioni desktop Java;
  • tool interni o utility locali;
  • prototipi rapidi;
  • demo didattiche;
  • piccoli database embedded;
  • test con persistenza reale su file;
  • applicazioni con pochi utenti o monoutente;
  • progetti in cui la semplicità di deploy è più importante della scalabilità.

Casi in cui è meglio valutare un altro database

  • applicazioni web con molti utenti concorrenti;
  • sistemi enterprise con molte scritture simultanee;
  • applicazioni distribuite;
  • microservizi in produzione ad alto carico;
  • progetti con forte bisogno di concorrenza in scrittura;
  • database di grandi dimensioni con workload complessi;
  • necessità avanzate di gestione utenti, permessi e amministrazione server.

SQLite è semplice, ma proprio questa semplicità comporta dei limiti. Hibernate può funzionare con SQLite, ma bisogna conoscere bene il contesto.

Hibernate supporta SQLite?

Storicamente, Hibernate non includeva un dialect ufficiale per SQLite tra quelli principali. Per questo motivo molti vecchi tutorial usavano dialect esterni creati dalla community, diversi a seconda della versione di Hibernate.

In vecchi progetti si trovano spesso riferimenti a:

  • dialect personalizzati per Hibernate 3;
  • dialect esterni per Hibernate 4;
  • classi SQLiteDialect copiate manualmente nel progetto;
  • repository GitHub non sempre mantenuti;
  • configurazioni basate su org.hibernate.dialect.Dialect esteso a mano.

Con Hibernate moderno, però, la situazione è più ordinata: il dialect SQLite è disponibile nel modulo hibernate-community-dialects.

Dialect moderno

org.hibernate.community.dialect.SQLiteDialect

Questo significa che, in un progetto con Hibernate 6 o successivo, la configurazione consigliata è usare il modulo community dialects e indicare questo dialect nella configurazione.

Nota importante: i dialect community non vanno confusi con i dialect principali supportati nel core. Sono comunque molto utili per database come SQLite, ma vanno sempre allineati alla versione di Hibernate usata nel progetto.

Driver JDBC per SQLite

Per collegare Java a SQLite serve un driver JDBC. Il driver più usato è:

org.xerial:sqlite-jdbc

La dipendenza Maven ha questa forma:

<dependency>
    <groupId>org.xerial</groupId>
    <artifactId>sqlite-jdbc</artifactId>
    <version>VERSIONE_DA_VERIFICARE</version>
</dependency>

Il driver permette a Java di aprire connessioni JDBC verso file SQLite.

URL JDBC SQLite

jdbc:sqlite:university.sqlite

Oppure con percorso assoluto:

jdbc:sqlite:/var/data/university.sqlite

Oppure in ambiente Windows:

jdbc:sqlite:C:/data/university.sqlite

Driver class

org.sqlite.JDBC

In molte configurazioni moderne il driver può essere rilevato automaticamente, ma indicarlo esplicitamente può rendere la configurazione più chiara.

SQLiteDialect in Hibernate

Hibernate usa un dialect per sapere come generare SQL compatibile con il database scelto.

Ogni database ha particolarità proprie: tipi di dato, sintassi SQL, gestione delle sequenze, limit, offset, identity, constraint e funzioni. Il dialect serve proprio a tradurre le operazioni ORM in SQL adatto al database.

Dialect per SQLite con Hibernate moderno

org.hibernate.community.dialect.SQLiteDialect

Configurazione Hibernate

hibernate.dialect=org.hibernate.community.dialect.SQLiteDialect

Configurazione Spring Boot

spring.jpa.database-platform=org.hibernate.community.dialect.SQLiteDialect

Per usare questo dialect, devi aggiungere la dipendenza hibernate-community-dialects con una versione compatibile con hibernate-core.

Regola pratica: usa la stessa versione per hibernate-core e hibernate-community-dialects, oppure lascia che Spring Boot gestisca le versioni quando possibile.

Dipendenze Maven

Vediamo una configurazione Maven moderna per usare Hibernate e SQLite.

Dipendenze con Hibernate 6

<dependencies>

    <dependency>
        <groupId>org.hibernate.orm</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>${hibernate.version}</version>
    </dependency>

    <dependency>
        <groupId>org.hibernate.orm</groupId>
        <artifactId>hibernate-community-dialects</artifactId>
        <version>${hibernate.version}</version>
    </dependency>

    <dependency>
        <groupId>org.xerial</groupId>
        <artifactId>sqlite-jdbc</artifactId>
        <version>${sqlite.jdbc.version}</version>
    </dependency>

</dependencies>

Proprietà Maven

<properties>
    <hibernate.version>VERSIONE_HIBERNATE_DA_VERIFICARE</hibernate.version>
    <sqlite.jdbc.version>VERSIONE_SQLITE_JDBC_DA_VERIFICARE</sqlite.jdbc.version>
</properties>

In un progetto reale è importante verificare le versioni aggiornate su Maven Central e mantenere compatibilità tra Hibernate core e community dialects.

Dipendenze con Spring Boot

Se usi Spring Boot, normalmente non specifichi direttamente la versione di Hibernate core, perché viene gestita dal dependency management di Spring Boot.

<dependencies>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <dependency>
        <groupId>org.hibernate.orm</groupId>
        <artifactId>hibernate-community-dialects</artifactId>
    </dependency>

    <dependency>
        <groupId>org.xerial</groupId>
        <artifactId>sqlite-jdbc</artifactId>
    </dependency>

</dependencies>

In alcuni casi può essere necessario specificare esplicitamente la versione del community dialects se non viene gestita dal BOM usato dal progetto.

Configurazione Hibernate nativa

In una configurazione Hibernate nativa, senza Spring Boot, possiamo usare un file hibernate.cfg.xml.

hibernate.cfg.xml

<hibernate-configuration>
    <session-factory>

        <property name="hibernate.connection.driver_class">
            org.sqlite.JDBC
        </property>

        <property name="hibernate.connection.url">
            jdbc:sqlite:university.sqlite
        </property>

        <property name="hibernate.dialect">
            org.hibernate.community.dialect.SQLiteDialect
        </property>

        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.format_sql">true</property>

        <property name="hibernate.hbm2ddl.auto">update</property>

        <mapping class="it.javaboss.model.Studente"/>
        <mapping class="it.javaboss.model.Indirizzo"/>
        <mapping class="it.javaboss.model.CorsoLaurea"/>
        <mapping class="it.javaboss.model.CorsoStudio"/>

    </session-factory>
</hibernate-configuration>

Le proprietà più importanti sono:

  • hibernate.connection.driver_class: indica il driver JDBC;
  • hibernate.connection.url: indica il file SQLite;
  • hibernate.dialect: indica il dialect SQLite;
  • hibernate.hbm2ddl.auto: indica come gestire lo schema;
  • hibernate.show_sql: mostra le query generate;
  • hibernate.format_sql: formatta le query nel log.

Creazione della SessionFactory

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {

    private static final SessionFactory sessionFactory = buildSessionFactory();

    private static SessionFactory buildSessionFactory() {
        return new Configuration()
                .configure("hibernate.cfg.xml")
                .buildSessionFactory();
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}

Configurazione JPA con persistence.xml

Se preferisci una configurazione JPA, puoi usare un file persistence.xml.

persistence.xml

<persistence xmlns="https://jakarta.ee/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence
             https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd"
             version="3.0">

    <persistence-unit name="sqlitePU">

        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

        <class>it.javaboss.model.Studente</class>
        <class>it.javaboss.model.Indirizzo</class>
        <class>it.javaboss.model.CorsoLaurea</class>
        <class>it.javaboss.model.CorsoStudio</class>

        <properties>
            <property name="jakarta.persistence.jdbc.driver" value="org.sqlite.JDBC" />
            <property name="jakarta.persistence.jdbc.url" value="jdbc:sqlite:university.sqlite" />

            <property name="hibernate.dialect" value="org.hibernate.community.dialect.SQLiteDialect" />
            <property name="hibernate.hbm2ddl.auto" value="update" />
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.format_sql" value="true" />
        </properties>

    </persistence-unit>

</persistence>

Creazione dell’EntityManagerFactory

import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.Persistence;

public class JpaUtil {

    private static final EntityManagerFactory entityManagerFactory =
            Persistence.createEntityManagerFactory("sqlitePU");

    public static EntityManagerFactory getEntityManagerFactory() {
        return entityManagerFactory;
    }
}

Questa configurazione è utile se vuoi lavorare con JPA standard invece che con API native di Hibernate.

Configurazione Spring Boot con Hibernate e SQLite

In un progetto moderno, è molto comune usare Spring Boot con Spring Data JPA e Hibernate.

application.properties

spring.datasource.url=jdbc:sqlite:university.sqlite
spring.datasource.driver-class-name=org.sqlite.JDBC

spring.jpa.database-platform=org.hibernate.community.dialect.SQLiteDialect
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

application.yml

spring:
  datasource:
    url: jdbc:sqlite:university.sqlite
    driver-class-name: org.sqlite.JDBC

  jpa:
    database-platform: org.hibernate.community.dialect.SQLiteDialect
    hibernate:
      ddl-auto: update
    show-sql: true
    properties:
      hibernate:
        format_sql: true

Questa configurazione dice a Spring Boot di usare SQLite come datasource e Hibernate come provider JPA.

Classe principale

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SQLiteHibernateApplication {

    public static void main(String[] args) {
        SpringApplication.run(SQLiteHibernateApplication.class, args);
    }
}

Nota pratica: in un progetto Spring Boot conviene usare Spring Data JPA per semplificare repository, transazioni e configurazione.

Entità di esempio

Vediamo alcune entità di esempio ispirate a un piccolo dominio universitario.

Studente

package it.javaboss.model;

import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;

@Entity
@Table(name = "studenti")
public class Studente {

    @Id
    private String matricola;

    private String nome;

    private String cognome;

    @ManyToOne
    @JoinColumn(name = "indirizzo_id")
    private Indirizzo indirizzo;

    @ManyToOne
    @JoinColumn(name = "corso_id")
    private CorsoStudio corso;

    public Studente() {
    }

    public Studente(String matricola, String nome, String cognome) {
        this.matricola = matricola;
        this.nome = nome;
        this.cognome = cognome;
    }

    public String getMatricola() {
        return matricola;
    }

    public void setMatricola(String matricola) {
        this.matricola = matricola;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public String getCognome() {
        return cognome;
    }

    public void setCognome(String cognome) {
        this.cognome = cognome;
    }

    public Indirizzo getIndirizzo() {
        return indirizzo;
    }

    public void setIndirizzo(Indirizzo indirizzo) {
        this.indirizzo = indirizzo;
    }

    public CorsoStudio getCorso() {
        return corso;
    }

    public void setCorso(CorsoStudio corso) {
        this.corso = corso;
    }
}

Indirizzo

package it.javaboss.model;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.Table;

@Entity
@Table(name = "indirizzi")
public class Indirizzo {

    @Id
    @GeneratedValue
    private Long id;

    private String strada;

    private String civico;

    private String cap;

    private String citta;

    public Indirizzo() {
    }

    public Indirizzo(String strada, String civico, String cap, String citta) {
        this.strada = strada;
        this.civico = civico;
        this.cap = cap;
        this.citta = citta;
    }

    public Long getId() {
        return id;
    }

    public String getStrada() {
        return strada;
    }

    public void setStrada(String strada) {
        this.strada = strada;
    }

    public String getCivico() {
        return civico;
    }

    public void setCivico(String civico) {
        this.civico = civico;
    }

    public String getCap() {
        return cap;
    }

    public void setCap(String cap) {
        this.cap = cap;
    }

    public String getCitta() {
        return citta;
    }

    public void setCitta(String citta) {
        this.citta = citta;
    }
}

CorsoLaurea

package it.javaboss.model;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.Table;

@Entity
@Table(name = "corsi_laurea")
public class CorsoLaurea {

    @Id
    @GeneratedValue
    private Long id;

    private String anno;

    private String facolta;

    public CorsoLaurea() {
    }

    public CorsoLaurea(String anno, String facolta) {
        this.anno = anno;
        this.facolta = facolta;
    }

    public Long getId() {
        return id;
    }

    public String getAnno() {
        return anno;
    }

    public void setAnno(String anno) {
        this.anno = anno;
    }

    public String getFacolta() {
        return facolta;
    }

    public void setFacolta(String facolta) {
        this.facolta = facolta;
    }
}

CorsoStudio

package it.javaboss.model;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;

@Entity
@Table(name = "corsi_studio")
public class CorsoStudio {

    @Id
    @GeneratedValue
    private Long id;

    private String nome;

    @ManyToOne
    @JoinColumn(name = "corso_laurea_id")
    private CorsoLaurea corsoLaurea;

    public CorsoStudio() {
    }

    public CorsoStudio(String nome, CorsoLaurea corsoLaurea) {
        this.nome = nome;
        this.corsoLaurea = corsoLaurea;
    }

    public Long getId() {
        return id;
    }

    public String getNome() {
        return nome;
    }

    public CorsoLaurea getCorsoLaurea() {
        return corsoLaurea;
    }
}

Repository e Service con Spring Data JPA

Con Spring Data JPA possiamo creare repository molto semplici.

StudenteRepository

package it.javaboss.repository;

import it.javaboss.model.Studente;
import org.springframework.data.jpa.repository.JpaRepository;

public interface StudenteRepository extends JpaRepository<Studente, String> {
}

IndirizzoRepository

package it.javaboss.repository;

import it.javaboss.model.Indirizzo;
import org.springframework.data.jpa.repository.JpaRepository;

public interface IndirizzoRepository extends JpaRepository<Indirizzo, Long> {
}

Service di esempio

package it.javaboss.service;

import it.javaboss.model.Studente;
import it.javaboss.repository.StudenteRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class StudenteService {

    private final StudenteRepository studenteRepository;

    public StudenteService(StudenteRepository studenteRepository) {
        this.studenteRepository = studenteRepository;
    }

    @Transactional(readOnly = true)
    public List<Studente> findAll() {
        return studenteRepository.findAll();
    }

    @Transactional
    public Studente save(Studente studente) {
        return studenteRepository.save(studente);
    }
}

Il codice applicativo lavora con entità Java, mentre Hibernate si occupa di generare SQL compatibile con SQLite.

Inizializzazione con import.sql

Hibernate può eseguire un file import.sql quando crea lo schema del database. Questo è utile per popolare dati iniziali in esempi, test o prototipi.

Il file va normalmente inserito in:

src/main/resources/import.sql

Esempio import.sql

INSERT INTO corsi_laurea (id, anno, facolta) VALUES (1, '2016', 'Ingegneria');

INSERT INTO corsi_studio (id, nome, corso_laurea_id) VALUES (1, 'Programmazione Java', 1);

INSERT INTO indirizzi (id, strada, civico, cap, citta) VALUES (1, 'VIA JAVA', '1', '00100', 'ROMA');

INSERT INTO studenti (matricola, nome, cognome, indirizzo_id, corso_id)
VALUES ('RM123MR', 'Java', 'Boss', 1, 1);

Questo file viene eseguito quando Hibernate crea il database, per esempio con:

spring.jpa.hibernate.ddl-auto=create

oppure:

hibernate.hbm2ddl.auto=create

Attenzione: usare create cancella e ricrea lo schema a ogni avvio. È utile per demo e test, ma pericoloso in ambienti reali.

hbm2ddl.auto: create, update, validate

La proprietà hibernate.hbm2ddl.auto controlla il comportamento di Hibernate rispetto allo schema del database.

Valore Comportamento Quando usarlo
create Crea lo schema da zero a ogni avvio. Demo, test, prototipi.
create-drop Crea lo schema e lo elimina alla chiusura. Test temporanei.
update Prova ad aggiornare lo schema esistente. Sviluppo locale, con cautela.
validate Verifica che lo schema corrisponda alle entità. Ambienti più controllati.
none Non modifica lo schema. Produzione o schema gestito manualmente.

Esempio Spring Boot

spring.jpa.hibernate.ddl-auto=update

Esempio Hibernate nativo

<property name="hibernate.hbm2ddl.auto">update</property>

Con SQLite bisogna prestare particolare attenzione a update, perché non tutte le modifiche di schema sono semplici o supportate nello stesso modo dei database server più completi.

Best practice: per ambienti reali, usa strumenti di migrazione come Flyway o Liquibase invece di affidarti completamente a hbm2ddl.auto.

Limiti di SQLite con Hibernate

SQLite è comodo, ma ha limiti importanti quando viene usato con Hibernate.

Concorrenza in scrittura

SQLite non è pensato per molte scritture concorrenti come un database server tradizionale. Per applicazioni web con molti utenti, PostgreSQL o MySQL sono spesso scelte più adatte.

Schema evolution

Alcune operazioni di modifica dello schema possono essere più limitate rispetto ad altri database. Questo può rendere meno affidabile l’uso automatico di hbm2ddl.auto=update.

Tipi di dato

SQLite ha un sistema di tipi più flessibile rispetto ad altri database. Questo può creare differenze rispetto a database più rigidi.

Funzionalità SQL avanzate

Alcune funzionalità SQL disponibili in database enterprise potrebbero non essere presenti o comportarsi in modo diverso.

Dialect community

Il dialect SQLite in Hibernate moderno si trova nei community dialects. È utile, ma va usato con attenzione e testato rispetto alle necessità del progetto.

Non ideale per alta scalabilità

SQLite è perfetto per semplicità e leggerezza, ma non sostituisce un database server in scenari enterprise ad alto carico.

Errori comuni

Dimenticare il dialect

Se non configuri il dialect, Hibernate potrebbe non sapere come generare SQL adatto a SQLite.

spring.jpa.database-platform=org.hibernate.community.dialect.SQLiteDialect

Dimenticare hibernate-community-dialects

Se usi org.hibernate.community.dialect.SQLiteDialect ma non aggiungi la dipendenza, otterrai un errore di classe non trovata.

ClassNotFoundException: org.hibernate.community.dialect.SQLiteDialect

Usare dialect vecchi con Hibernate moderno

Vecchi dialect esterni pensati per Hibernate 3 o 4 possono non funzionare con Hibernate 6.

Usare javax.persistence in progetti Jakarta

Con Spring Boot 3 e Hibernate 6 si usano package jakarta.persistence.*, non javax.persistence.*.

Usare create in modo pericoloso

La configurazione:

hibernate.hbm2ddl.auto=create

ricrea lo schema a ogni avvio e può cancellare dati esistenti.

Usare SQLite per applicazioni ad alta concorrenza

SQLite non è sempre adatto per applicazioni web multiutente con molte scritture simultanee.

Non controllare il percorso del file database

Un URL come:

jdbc:sqlite:university.sqlite

crea il file nella working directory dell’applicazione. In produzione o in test può non essere la cartella che ti aspetti.

Best practice per usare Hibernate con SQLite

  • Usa org.xerial:sqlite-jdbc come driver JDBC.
  • Usa org.hibernate.community.dialect.SQLiteDialect con Hibernate moderno.
  • Allinea la versione di hibernate-community-dialects alla versione di Hibernate core.
  • Evita dialect esterni vecchi se usi Hibernate 6 o superiore.
  • Usa jakarta.persistence.* nei progetti Spring Boot 3 / Hibernate 6.
  • Non usare hbm2ddl.auto=create su dati importanti.
  • Specifica un percorso chiaro per il file SQLite.
  • Usa Flyway o Liquibase per migrazioni reali.
  • Testa bene query, relazioni e generazione dello schema.
  • Non scegliere SQLite per applicazioni con molte scritture concorrenti.
  • Usa SQLite per prototipi, tool locali, demo, test e applicazioni leggere.

Confronto: SQLite, H2, PostgreSQL e MySQL

Database Quando usarlo Limite principale
SQLite Applicazioni locali, monoutente, prototipi, file embedded. Non ideale per molte scritture concorrenti.
H2 Test, sviluppo, database in-memory. Può differire dal database reale di produzione.
PostgreSQL Applicazioni web, enterprise, dati complessi. Richiede server e configurazione.
MySQL Applicazioni web, gestionali, sistemi tradizionali. Richiede server e amministrazione.

SQLite è molto comodo quando vuoi portabilità e semplicità. Per applicazioni server-side con più utenti, spesso è meglio scegliere un database server.

Checklist di configurazione

Controllo Domanda da farsi
Driver JDBC Hai aggiunto org.xerial:sqlite-jdbc?
Dialect Hai configurato org.hibernate.community.dialect.SQLiteDialect?
Community dialects Hai aggiunto hibernate-community-dialects?
Versioni Le versioni di Hibernate core e community dialects sono compatibili?
URL database Il percorso del file SQLite è quello corretto?
Schema Stai usando create, update o migrazioni controllate?
Concorrenza SQLite è adatto al carico previsto?
Ambiente È un prototipo, un tool locale o una vera applicazione server?

FAQ su Hibernate e SQLite

Hibernate supporta SQLite?

Hibernate può lavorare con SQLite usando un driver JDBC e un dialect adatto. Nei progetti moderni si può usare org.hibernate.community.dialect.SQLiteDialect dal modulo hibernate-community-dialects.

Quale driver JDBC usare per SQLite?

Il driver più usato è org.xerial:sqlite-jdbc.

Quale dialect usare con Hibernate 6 e SQLite?

Con Hibernate moderno puoi usare:

org.hibernate.community.dialect.SQLiteDialect

Come configurare SQLite in Spring Boot?

Una configurazione base è:

spring.datasource.url=jdbc:sqlite:university.sqlite
spring.datasource.driver-class-name=org.sqlite.JDBC
spring.jpa.database-platform=org.hibernate.community.dialect.SQLiteDialect

Perché ricevo ClassNotFoundException per SQLiteDialect?

Probabilmente hai configurato il dialect ma non hai aggiunto la dipendenza hibernate-community-dialects.

SQLite è adatto alla produzione?

Dipende dal tipo di applicazione. Può essere adatto a tool locali, applicazioni embedded o monoutente. Per applicazioni web con molti utenti concorrenti, spesso è meglio usare PostgreSQL, MySQL o un database server.

Posso usare hbm2ddl.auto=create con SQLite?

Sì, ma con cautela. create ricrea lo schema a ogni avvio e può cancellare i dati esistenti.

Posso usare import.sql con SQLite e Hibernate?

Sì. Se Hibernate crea lo schema, può eseguire import.sql presente nel classpath per inserire dati iniziali.

Meglio SQLite o H2 per i test?

H2 è molto comodo per test in-memory, ma SQLite può essere utile se vuoi testare un database su file più simile allo scenario embedded reale.

Devo usare javax.persistence o jakarta.persistence?

Con Hibernate 6 e Spring Boot 3 si usa jakarta.persistence.*. Nei progetti legacy con Hibernate 4 o 5 puoi trovare javax.persistence.*.

Posso usare SQLite con Spring Data JPA?

Sì, configurando correttamente datasource, driver JDBC, dialect Hibernate e dipendenze necessarie.

Conclusione

Usare Hibernate e SQLite insieme è possibile e può essere molto utile in diversi scenari: applicazioni desktop, tool locali, prototipi, test, demo e piccoli sistemi embedded. SQLite è leggero e pratico, mentre Hibernate permette di lavorare con entità Java, relazioni e repository invece di gestire manualmente tutto il codice JDBC.

La configurazione moderna richiede principalmente due dipendenze: il driver org.xerial:sqlite-jdbc e il modulo hibernate-community-dialects, che contiene org.hibernate.community.dialect.SQLiteDialect.

Rispetto ai vecchi esempi basati su Hibernate 3, 4 o 5, oggi è preferibile evitare dialect esterni non mantenuti e usare il dialect community fornito dall’ecosistema Hibernate moderno.

SQLite resta però un database con caratteristiche specifiche. È molto comodo quando vuoi semplicità, portabilità e un database in un singolo file. Non è sempre la scelta giusta per applicazioni web multiutente, carichi elevati o molte scritture concorrenti.

Riassunto finale: Hibernate può lavorare con SQLite usando sqlite-jdbc e SQLiteDialect. È una soluzione pratica per applicazioni leggere e prototipi, ma per sistemi enterprise o web ad alta concorrenza conviene valutare database server come PostgreSQL o MySQL.

Risorse ufficiali utili