Persistencia (Hibernate / JPA)¶
Cómo persiste el backend: provider, dialecto propio, modo de flush, naming strategy y administración del DDL. Todo está configurado en application.yml y en com.tipre.tifacturaonlinemanager.action.db.SQLServerDialect + config.SeamCompatConfig. Para las entidades concretas ver Modelo de dominio; para por qué el flush es MANUAL, Invariantes.
De un vistazo¶
| Aspecto | Valor | Dónde |
|---|---|---|
| Provider | Hibernate 7.2.x (vía BOM Spring Boot 4.0) | pom.xml (BOM) |
| Starter | spring-boot-starter-data-jpa |
pom.xml |
| Dialecto | com.tipre.tifacturaonlinemanager.action.db.SQLServerDialect (propio) |
spring.jpa.database-platform |
ddl-auto |
none |
application.yml |
| Naming físico | PhysicalNamingStrategyStandardImpl |
application.yml |
open-in-view |
false |
application.yml |
| Flush por defecto | MANUAL (FlushModeType.COMMIT en el entityManager del shim) |
SeamCompatConfig |
| Driver | com.microsoft.sqlserver.jdbc.SQLServerDriver (mssql-jdbc 12.8.1.jre11) |
pom.xml + application-{dev,prod}.yml |
| Cache 2do nivel | No (sin @Cache; dependencia comentada en pom.xml) |
— |
| Tests | H2 (src/test/resources/application.yml pisa al base) |
pom.xml (scope test) |
Dialecto propio: SQLServerDialect¶
action/db/SQLServerDialect.java extiende org.hibernate.dialect.SQLServerDialect (el de Hibernate, ya version-aware) y solo sobreescribe el mapeo de BOOLEAN:
public class SQLServerDialect extends org.hibernate.dialect.SQLServerDialect {
@Override
protected String columnType(int sqlTypeCode) {
if (sqlTypeCode == SqlTypes.BOOLEAN) {
return "bit";
}
return super.columnType(sqlTypeCode);
}
}
Es un port del legacy (SPEC-002): el legacy registraba BOOLEAN -> "bit" para que los boolean del modelo (p. ej. EnteFacturador.habilitado, los flags de TipoComprobante) mapeen a columnas bit de SQL Server.
Hibernate 6 cambió la API
Hibernate 6 eliminó los dialectos versionados (SQLServer2012Dialect) y la API registerColumnType(int, String). El reemplazo idiomático es extender SQLServerDialect y sobreescribir columnType(int). El comentario del propio archivo lo deja claro.
El dialecto es prácticamente inerte
Con hbm2ddl=none la generación de DDL está deshabilitada, así que el override de BOOLEAN->bit solo afectaría a la generación de DDL, que no ocurre. Se conserva por fidelidad al legacy y trazabilidad (SPEC-002), no porque cambie el runtime.
DDL administrado por el cliente¶
spring.jpa.hibernate.ddl-auto: none. El esquema lo administra el cliente, la app NO lo genera ni lo altera. Esta es una invariante explícita en application.yml.
Las tablas nuevas que introdujo la migración (no del legacy) se versionan como scripts SQL en src/main/resources/db/migration/ para que el cliente los aplique a mano (no es Flyway/Liquibase automático — son scripts de referencia):
add-JobEjecucion.sql— tablaJobEjecucion.add-TrxErrorLog.sql— tablaTrxErrorLog.add-cert-EntesFacturadores.sql— columnascertP12*enEntesFacturadores.add-validadoArca-SucPosPV.sql,add-unique-indexes-SucPosPV.sql,add-PV-validacion-obtencion-SucPosPV.sql— columnas/índices deSucPosPV.add-CockpitStat.sql,add-Trx-*.sql,schedule-nc-job.sql,cleanup-parametros-legacy.sql,drop-tablas-sin-uso.sql,verify-cae-caea-nc.sql.
Validar mapeos contra la DB real
El perfil de test application-realdb.yml (LOCAL, gitignored) apunta a una copia de prod restaurada y usa ddl-auto: none igualmente — la validación real son las queries del test, no el validate de Hibernate (pedante con tipos equivalentes como numeric vs bigint que en runtime andan).
Naming strategy¶
spring.jpa.hibernate.naming.physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl.
La estrategia estándar respeta @Table/@Column tal cual: nombres literales en PascalCase, sin convertir a snake_case. Es el comportamiento del Hibernate 4 del legacy. Por eso las entidades pueden mapear tablas como EntesFacturadores, TiposComprobante, Caeas o columnas como idEnteFacturador y fFechaUltObtencionPOS sin transformación.
Flush MANUAL¶
El bean entityManager que usa el seam-compat se crea en SeamCompatConfig como shared entity manager y se le fija FlushModeType.COMMIT:
@Bean(name = "entityManager")
public EntityManager seamEntityManager(EntityManagerFactory emf) {
EntityManager em = SharedEntityManagerCreator.createSharedEntityManager(emf);
try { em.setFlushMode(FlushModeType.COMMIT); } catch (Exception ignored) {} // INVARIANTE 5.1 (MANUAL ~ COMMIT)
return em;
}
Esto replica el default-flush-mode=MANUAL del components.xml legacy. En JPA no existe un MANUAL puro; COMMIT es el equivalente más cercano: Hibernate no auto-flushea antes de cada query, solo al commit de la transacción (o cuando se llama a flush() explícitamente).
Por eso el código de negocio hace flush() a mano donde necesita que algo pegue en la DB. El EntityHome del shim lo hace en persist()/update()/remove():
// org/jboss/seam/framework/EntityHome.java
getEntityManager().flush(); // INVARIANTE: flush explícito (modo MANUAL)
...
getEntityManager().flush(); // INVARIANTE 5.2: SOLO flush, sin merge
update() = solo flush, sin merge (invariante §5.2)
EntityHome.update() hace únicamente flush() sobre la entidad ya managed; no llama a merge(). El patrón de negocio (ParentEntityManager.updateOrPersistTrx) carga/setea la instancia en el Home y la deja en estado managed para que el flush la escriba. Romper esto (meter un merge) cambia la semántica de persistencia.
Otros puntos con flush() explícito: SucPosPVAdminService (backstop para que una violación de UQ salte en el flush y no en el commit), CaeaConsultaService, CockpitStatSnapshot, TrxNextGenPersistHelper.
Driver y datasource¶
Driver mssql-jdbc 12.8.1.jre11 (scope runtime; inerte en tests, que usan H2). La URL JDBC incluye encrypt=true;trustServerCertificate=true en dev y prod:
Detalle de hosts/credenciales por perfil y variables de entorno en Config y perfiles.
Cache de segundo nivel¶
No hay 2nd-level cache hoy
El legacy tenía 2nd-level + query cache con ehcache (persistence-prod.xml), pero ninguna entidad migrada lleva @Cache, así que el cache no se usa. La dependencia (hibernate-jcache + ehcache) está comentada en el pom.xml (rotulada SPEC-002): hibernate-ehcache no existe en Hibernate 7 (el 2nd-level pasó a JCache), y habría que reescribir el bloque al abordar SPEC-002. open-in-view está en false, así que tampoco hay sesión abierta en la capa de vista.
Por dónde seguir¶
- Modelo de dominio — entidades y sus tablas.
- Config y perfiles — datasource por perfil y env vars.
- Invariantes — flush, idempotencia, lookup.