diff --git a/db/sql/mssql/feature/internals/transaction-log.txt b/db/sql/mssql/feature/internals/transaction-log.txt new file mode 100644 index 000000000..ab5e4fdc0 --- /dev/null +++ b/db/sql/mssql/feature/internals/transaction-log.txt @@ -0,0 +1 @@ +https://learn.microsoft.com/en-us/sql/relational-databases/logs/the-transaction-log-sql-server diff --git a/pl/java/libfws/spring/boot/features/cfg/properties.txt b/pl/java/libfws/spring/boot/features/cfg/properties.txt index 6fcc1dd90..de75a2093 100644 --- a/pl/java/libfws/spring/boot/features/cfg/properties.txt +++ b/pl/java/libfws/spring/boot/features/cfg/properties.txt @@ -5,9 +5,14 @@ https://www.baeldung.com/spring-reloading-properties 2021 https://www.baeldung.com/spring-yaml 2020 +https://www.baeldung.com/spring-enable-config-properties + @EnableConfigurationProperties + Enable support for @ConfigurationProperties annotated beans https://www.baeldung.com/properties-with-spring https://www.baeldung.com/configuration-properties-in-spring-boot - @ConfigurationProperties + classes, annotated with just + @ConfigurationProperties(prefix=) + are still simple POJOs https://github.com/eugenp/tutorials/tree/master/spring-boot-modules/spring-boot-properties system-properties diff --git a/pl/java/libfws/spring/data/jpa/features/collections.txt b/pl/java/libfws/spring/data/jpa/features/collections.txt new file mode 100644 index 000000000..1a983491d --- /dev/null +++ b/pl/java/libfws/spring/data/jpa/features/collections.txt @@ -0,0 +1,13 @@ +MarkdownUserModel { + ... + @Column(unique=true) + private String username; + ... + @ElementCollection(fetch = FetchType.LAZY) + private List roles; +} + +... +at repo +@EntityGraph(attributePaths="roles") +Optional findByUsername(String username); diff --git a/pl/java/libfws/spring/data/jpa/features/internals/hbm-dirty-checking.txt b/pl/java/libfws/spring/data/jpa/features/internals/hbm-dirty-checking.txt new file mode 100644 index 000000000..f8e6c4792 --- /dev/null +++ b/pl/java/libfws/spring/data/jpa/features/internals/hbm-dirty-checking.txt @@ -0,0 +1 @@ +dirty checking diff --git a/pl/java/libfws/spring/data/jpa/features/internals/hbm-loader.txt b/pl/java/libfws/spring/data/jpa/features/internals/hbm-loader.txt new file mode 100644 index 000000000..b4ce26027 --- /dev/null +++ b/pl/java/libfws/spring/data/jpa/features/internals/hbm-loader.txt @@ -0,0 +1,113 @@ +org.hibernate.loader + public abstract class Loader { + list() { + listIgnoreQueryCache(...) + } + private List listIgnoreQueryCache(SharedSessionContractImplementor session, QueryParameters queryParameters) { + return getResultList( doList( session, queryParameters ), queryParameters.getResultTransformer() ); + } + private List doQuery(...) { + final SqlStatementWrapper wrapper = executeQueryStatement( queryParameters, false, afterLoadActions, session ); + final ResultSet rs = wrapper.getResultSet(); + final Statement st = wrapper.getStatement(); + ... + try { + return processResultSet( + rs, + queryParameters, + session, + returnProxies, + forcedResultTransformer, + maxRows, + afterLoadActions + ); + } + ... + } + protected List processResultSet(...) { + final List results = getRowsFromResultSet( + initializeEntitiesAndCollections( + hydratedObjects, + rs, + session, + queryParameters.isReadOnly( session ), + afterLoadActions + ); + if ( createSubselects ) { + createSubselects( subselectResultKeys, queryParameters, session ); + } + return results; + } + protected List getRowsFromResultSet( + ResultSet rs, + QueryParameters queryParameters, + SharedSessionContractImplementor session, + boolean returnProxies, + ResultTransformer forcedResultTransformer, + int maxRows, + List hydratedObjects, + List subselectResultKeys) throws SQLException { + ... + LOG.trace( "Processing result set" ); + int count; + + final boolean debugEnabled = LOG.isDebugEnabled(); + for ( count = 0; count < maxRows && rs.next(); count++ ) { + if ( debugEnabled ) { + LOG.debugf( "Result set row: %s", count ); + } + Object result = getRowFromResultSet( + rs, + session, + queryParameters, + lockModesArray, + optionalObjectKey, + hydratedObjects, + keys, + returnProxies, + forcedResultTransformer + ); + results.add( result ); + if ( createSubselects ) { + subselectResultKeys.add( keys ); + keys = new EntityKey[entitySpan]; //can't reuse in this case + } + } + + LOG.tracev( "Done processing result set ({0} rows)", count ); + + return results; + } + private Object getRowFromResultSet(..) { + ... + // this call is side-effecty + Object[] row = getRow( + resultSet, + persisters, + keys, + queryParameters.getOptionalObject(), + optionalObjectKey, + lockModesArray, + hydratedObjects, + session + ); + ... + } + getRaw(...) { + } + /** + * Hydrate the state an object from the SQL ResultSet, into + * an array or "hydrated" values (do not resolve associations yet), + * and pass the hydrates state to the session. + */ + private void loadFromResultSet(...) { + } + } + +// * A delegate that implements the Loader part of QueryTranslator. +public class QueryLoader extends BasicLoader { + + // The query translator that is delegating to this object. + private QueryTranslatorImpl queryTranslator; + ... +} diff --git a/pl/java/libfws/spring/data/jpa/features/internals/hbm-query-plan.txt b/pl/java/libfws/spring/data/jpa/features/internals/hbm-query-plan.txt new file mode 100644 index 000000000..8990e938f --- /dev/null +++ b/pl/java/libfws/spring/data/jpa/features/internals/hbm-query-plan.txt @@ -0,0 +1,276 @@ +https://hibernate.atlassian.net/jira/software/c/projects/HHH/issues/HHH-11208 + +cfg +https://github.com/hibernate/hibernate-orm/blob/5.6/hibernate-core/src/main/java/org/hibernate/cfg/Environment.java +https://github.com/hibernate/hibernate-orm/blob/5.6/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java + /** + * Raises an exception when in-memory pagination over collection fetch is about to be performed. + * Disabled by default. Set to true to enable. + */ + String FAIL_ON_PAGINATION_OVER_COLLECTION_FETCH = "hibernate.query.fail_on_pagination_over_collection_fetch"; + + +SqlGenerator +QueryPlanCache +unwrap( org.hibernate.internal.QueryImpl.class ).setQueryPlan + +https://github.com/hibernate/hibernate-orm/tree/5.6/hibernate-core/src/main/java/org/hibernate/engine/query/spi +https://docs.jboss.org/hibernate/orm/5.4/javadocs/org/hibernate/engine/query/spi/package-frame.html + + +HQLQueryPlan + SessionFactoryBuilderImpl + @Override + public SessionFactory build() { + ... + // QueryPlanCreator=HQLQueryPlan::new + return new SessionFactoryImpl( metadata, buildSessionFactoryOptions(), HQLQueryPlan::new); // this is just a c-tor + } +https://docs.jboss.org/hibernate/orm/5.4/javadocs/org/hibernate/engine/query/spi/HQLQueryPlan.html +https://github.com/hibernate/hibernate-orm/blob/5.4/hibernate-core/src/main/java/org/hibernate/engine/query/spi/HQLQueryPlan.java + // Defines a query execution plan for an HQL query (or filter). + public class HQLQueryPlan implements Serializable { + protected HQLQueryPlan( + String hql, + String collectionRole, + boolean shallow, + Map enabledFilters, + SessionFactoryImplementor factory, + EntityGraphQueryHint entityGraphQueryHint) { + this.sourceQuery = hql; + this.shallow = shallow; + + if ( enabledFilters.isEmpty() ) { + this.enabledFilterNames = Collections.emptySet(); + } + else { + this.enabledFilterNames = Collections.unmodifiableSet( new HashSet<>( enabledFilters.keySet() ) ); + } + + final String[] concreteQueryStrings = QuerySplitter.concreteQueries( hql, factory ); + final int length = concreteQueryStrings.length; + this.translators = new QueryTranslator[length]; + + final Set combinedQuerySpaces = new HashSet<>(); + + final Map querySubstitutions = factory.getSessionFactoryOptions().getQuerySubstitutions(); + final QueryTranslatorFactory queryTranslatorFactory = factory.getServiceRegistry().getService( QueryTranslatorFactory.class ); + + + for ( int i=0; i 1 ) ? new Type[translators[0].getReturnTypes().length] : translators[0].getReturnTypes(); + returnMetadata = new ReturnMetadata( translators[0].getReturnAliases(), types ); + } + } + } + + public List performList(...) { + ... + for ( QueryTranslator translator : translators ) { + final List tmp = translator.list( session, queryParametersToUse ); + } + ... + } + } + +https://docs.jboss.org/hibernate/orm/5.4/javadocs/org/hibernate/engine/query/spi/FilterQueryPlan.html +https://docs.jboss.org/hibernate/orm/5.4/javadocs/org/hibernate/engine/query/spi/NativeSQLQueryPlan.html + https://github.com/hibernate/hibernate-orm/blob/5.5/hibernate-core/src/main/java/org/hibernate/engine/query/spi/NativeQueryInterpreter.java + NativeSQLQueryPlan createQueryPlan(...) + +https://docs.jboss.org/hibernate/orm/5.4/javadocs/org/hibernate/engine/query/spi/QueryPlanCache.html +https://github.com/hibernate/hibernate-orm/blob/5.4/hibernate-core/src/main/java/org/hibernate/engine/query/spi/QueryPlanCache.java + @FunctionalInterface + public interface QueryPlanCreator { + HQLQueryPlan createQueryPlan(String queryString, boolean shallow, Map enabledFilters, SessionFactoryImplementor factory); + } + + public QueryPlanCache(final SessionFactoryImplementor factory, QueryPlanCreator queryPlanCreator) { + ... + // Environment.QUERY_PLAN_CACHE_PARAMETER_METADATA_MAX_SIZE, + } + + public HQLQueryPlan getHQLQueryPlan(String queryString, boolean shallow, Map enabledFilters) throws QueryException, MappingException { + final HQLQueryPlanKey key = new HQLQueryPlanKey(queryString, shallow, enabledFilters); + HQLQueryPlan value = (HQLQueryPlan) queryPlanCache.get( key ); + final StatisticsImplementor statistics = factory.getStatistics(); + boolean stats = statistics.isStatisticsEnabled(); + if (value == null) { + final long startTime = ( stats ) ? System.nanoTime() : 0L; + + LOG.tracev( "Unable to locate HQL query plan in cache; generating ({0})", queryString ); + value = queryPlanCreator.createQueryPlan( queryString, shallow, enabledFilters, factory ); + ... + } + + public NativeSQLQueryPlan getNativeSQLQueryPlan(final NativeSQLQuerySpecification spec) { + ..veQueryInterpreter.createQueryPlan( spec, factory ); + } + + +org.hibernate.hql.internal.ast. + ASTQueryTranslatorFactory { + ... + @Override + public QueryTranslator createQueryTranslator( + String queryIdentifier, + String queryString, + Map filters, + SessionFactoryImplementor factory, + EntityGraphQueryHint entityGraphQueryHint) { + return new QueryTranslatorImpl( queryIdentifier, queryString, filters, factory, entityGraphQueryHint ); + } + } + public class QueryTranslatorImpl implements FilterTranslator { + ... + c-tor(... EntityGraphQueryHint entityGraphQueryHint) + + private HqlSqlWalker analyze(HqlParser parser, String collectionRole) throws QueryException, RecognitionException { + ... + LOG.debug( TokenPrinters.SQL_TOKEN_PRINTER.showAsString( w.getAST(), "--- SQL AST ---" ) ); + ... + } + void showHqlAst(AST hqlAst) { + if ( LOG.isDebugEnabled() ) { + LOG.debug( TokenPrinters.HQL_TOKEN_PRINTER.showAsString( hqlAst, "--- HQL AST ---" ) ); + } + } + @Override + public List list(SharedSessionContractImplementor session, QueryParameters queryParameters) throws HibernateException { + // Delegate to the QueryLoader... + ... + List results = queryLoader.list( session, queryParametersToUse ); + ... + } + @Override + public Iterator iterate(QueryParameters queryParameters, EventSource session) throws HibernateException { + // Delegate to the QueryLoader... + ... + return queryLoader.iterate( queryParameters, session ); + } + @Override + public ScrollableResultsImplementor scroll(QueryParameters queryParameters, SharedSessionContractImplementor session) throws HibernateException { + // Delegate to the QueryLoader... + ... + return queryLoader.scroll( queryParameters, session ); + } + // update stuff + + public EntityGraphQueryHint getEntityGraphQueryHint() { + return entityGraphQueryHint; + } + + public void setEntityGraphQueryHint(EntityGraphQueryHint entityGraphQueryHint) { + this.entityGraphQueryHint = entityGraphQueryHint; + } + } + + public final class HqlParser extends HqlBaseParser { + ... + } + + public class SqlGenerator extends SqlGeneratorBase implements ErrorReporter { + ... + } + HqlSqlWalker + +org.hibernate.loader.hql + QueryLoader + list() -> call Loader + +org.hibernate.loader + public abstract class Loader { + ... // separate file + } + + +? +org.hibernate.hql.internal.classic.QueryTranslatorImpl + /** + * Compile the query (generate the SQL). + */ + private void compile() throws QueryException, MappingException { + try { + ParserHelper.parse( + new PreprocessingParser( tokenReplacements ), + queryString, + ParserHelper.HQL_SEPARATORS, + this + ); + renderSQL(); + } + postInstantiate(); + compiled = true; + } + private void renderSQL() throws QueryException, MappingException { + } + protected void postInstantiate() { + ... + fill descriptors (DefaultEntityAliases), collectionDescriptors (ColllectionAliases, GeneratedCollectionAliases) + // ? ColumnCollectionAliases org.hibernate.loader.custom + } + + +at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:189) +at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:144) +at org.hibernate.engine.query.spi.HQLQueryPlan.(HQLQueryPlan.java:113) +at org.hibernate.engine.query.spi.HQLQueryPlan.(HQLQueryPlan.java:73) +at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:155) +at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:604) + +? EntityPersister, +org.hibernate.persister.entity.AbstractClassEntityPersister +org.hibernate.hql.internal.classic + PreprocessingParser + uses QueryTranslatorImpl (?classic) + -> ClauseParser !!! + HavingParser + GroupByParser + ... + + +??? +org.hibernate.graph + GraphParser // for tests only + * Parser for string representations of JPA {@link javax.persistence.EntityGraph} + * ({@link RootGraph}) and {@link javax.persistence.Subgraph} ({@link SubGraph}), + * using a simple syntax defined by the `graph.g` Antlr grammar. + +org.hibernate.jpa + QueryHints { + ... + CACHEMODE, FLUSHMODE + ... + public static final String COMMENT = "org.hibernate.comment"; + ... + public static final String FOLLOW_ON_LOCKING = "hibernate.query.followOnLocking"; + public static final String HINT_FOLLOW_ON_LOCKING = FOLLOW_ON_LOCKING; + tons of JPA hints + public static final String HINT_FETCHGRAPH = GraphSemantic.FETCH.getJpaHintName(); + public static final String HINT_LOADGRAPH = GraphSemantic.LOAD.getJpaHintName(); + } diff --git a/pl/java/libfws/spring/data/jpa/features/internals/hql-jpql.txt b/pl/java/libfws/spring/data/jpa/features/internals/hql-jpql.txt new file mode 100644 index 000000000..594334d68 --- /dev/null +++ b/pl/java/libfws/spring/data/jpa/features/internals/hql-jpql.txt @@ -0,0 +1,6 @@ +https://docs.jboss.org/hibernate/orm/4.3/devguide/en-US/html/ch11.html + 11.3.3. Explicit joins + An important use case for explicit joins is to define FETCH JOINS which override the laziness of the joined association + left join fetch + +https://github.com/hibernate/hibernate-orm/blob/5.4/hibernate-core/src/main/antlr/hql.g diff --git a/pl/java/libfws/spring/data/jpa/features/nplusone/entity-graphs.txt b/pl/java/libfws/spring/data/jpa/features/nplusone/entity-graphs.txt index 1367a231f..412a7ddad 100644 --- a/pl/java/libfws/spring/data/jpa/features/nplusone/entity-graphs.txt +++ b/pl/java/libfws/spring/data/jpa/features/nplusone/entity-graphs.txt @@ -6,6 +6,9 @@ https://www.baeldung.com/hibernate-common-performance-problems-in-logs https://thorben-janssen.com/jpa-21-entity-graph-part-2-define/ https://www.baeldung.com/spring-data-jpa-named-entity-graphs 2021 +https://foojay.io/today/a-walk-to-lazy-fetching-with-hibernate-and-spring-data-jpa/ + https://github.com/mainul35/social-community + ! pure hbm https://vladmihalcea.com/jpa-entity-graph/ https://vladmihalcea.com/jpa-default-fetch-plan/ ! @@ -29,3 +32,6 @@ https://stackoverflow.com/questions/71175593/how-does-jpa-entitygraph-allow-chos 2019 https://www.youtube.com/watch?v=b2a4rVR5hiQ + + +pvt/idp/loyalty/loyalty-mock-service