{"id":15019666,"url":"https://github.com/starnowski/posjsonhelper","last_synced_at":"2025-10-24T11:49:33.028Z","repository":{"id":36354493,"uuid":"162270870","full_name":"starnowski/posjsonhelper","owner":"starnowski","description":"The Posjsonhelper library is an open-source project that adds support for Hibernate queries for Postgresql JSON functions and full-text search.","archived":false,"fork":false,"pushed_at":"2024-05-01T13:20:50.000Z","size":1706,"stargazers_count":7,"open_issues_count":5,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-05-01T16:44:11.871Z","etag":null,"topics":["full-text-search","hibernate","json","jsonb","postgres","postgresql","text-search"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-2.1","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/starnowski.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-12-18T10:27:56.000Z","updated_at":"2024-05-21T23:27:09.375Z","dependencies_parsed_at":"2023-12-28T22:23:18.059Z","dependency_job_id":"25c5737a-7e7b-4dd4-9825-64ea6308bb21","html_url":"https://github.com/starnowski/posjsonhelper","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/starnowski/posjsonhelper","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/starnowski%2Fposjsonhelper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/starnowski%2Fposjsonhelper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/starnowski%2Fposjsonhelper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/starnowski%2Fposjsonhelper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/starnowski","download_url":"https://codeload.github.com/starnowski/posjsonhelper/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/starnowski%2Fposjsonhelper/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261101617,"owners_count":23109860,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["full-text-search","hibernate","json","jsonb","postgres","postgresql","text-search"],"created_at":"2024-09-24T19:53:52.071Z","updated_at":"2025-10-24T11:49:33.021Z","avatar_url":"https://github.com/starnowski.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# posjsonhelper\n\n[![Run tests for posjsonhelper](https://github.com/starnowski/posjsonhelper/actions/workflows/ci.yml/badge.svg)](https://github.com/starnowski/posjsonhelper/actions/workflows/ci.yml)\n[![Maven Central](https://img.shields.io/maven-central/v/com.github.starnowski.posjsonhelper/parent.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22com.github.starnowski.posjsonhelper%22%20AND%20a:%22parent%22)\n[![Run forward compatibility tests for posjsonhelper](https://github.com/starnowski/posjsonhelper/actions/workflows/forward_compatibility.yml/badge.svg)](https://github.com/starnowski/posjsonhelper/actions/workflows/forward_compatibility.yml)\n\n* [Introduction](#introduction)\n* [How to start using posjsonhelper](#how-to-start-using-posjsonhelper)\n    * [Setting maven dependency](#setting-maven-dependency)\n      * [Optional dependencies](#optional-dependencies)\n    * [Building project locally](#building-project-locally)\n* [How to attach postgresql_dialect](#how-to-attach-postgresql-dialect)\n* [How to attach FunctionContributor](#how-to-attach-functioncontributor)\n* [Apply DDL changes](#apply-ddl-changes)\n    * [Apply DDL changes programmatically](#apply-ddl-changes-programmatically)\n    * [Core context](#core-context)\n* [How to use query helper](#how-to-use-query-helper)\n    * [Hibernate Context](#hibernate-context)\n    * [JsonBExtractPath - jsonb_extract_path](#jsonbextractpath---jsonb_extract_path)\n    * [JsonBExtractPathText - jsonb_extract_path_text](#jsonbextractpathtext---jsonb_extract_path_text)\n    * [JsonbAllArrayStringsExistPredicate](#jsonballarraystringsexistpredicate)\n    * [JsonbAnyArrayStringsExistPredicate](#jsonbanyarraystringsexistpredicate)\n* [Modify JSON](#modify-json)\n  * [jsonb_set function wrapper](#jsonb_set-function-wrapper)\n  * [Concatenation operator wrapper '||'](#concatenation-operator-wrapper-)\n  * [Delete the field or array element based on the index at the specified path '#-'](#delete-the-field-or-array-element-based-on-the-index-at-the-specified-path--)\n  * [Delete a multiple array elements at the specified path '#-'](#delete-a-multiple-array-elements-at-the-specified-path--)\n  * [Hibernate6JsonUpdateStatementBuilder - How to combine multiple modification operations with one update statement?](#hibernate6jsonupdatestatementbuilder---how-to-combine-multiple-modification-operations-with-one-update-statement)\n    * [How to add custom value support for Hibernate6JsonUpdateStatementBuilder?](#how-to-add-custom-value-support-for-hibernate6jsonupdatestatementbuilder)\n* [Properties](#properties)\n* [Reporting issues](#reporting-issues)\n* [Project contribution](#project-contribution)\n\n# Introduction\nPosjsonhelper library is an open-source project that adds support of Hibernate query for [postgresql json functions](https://www.postgresql.org/docs/10/functions-json.html).\nLibrary also has support for [postgresql text search functions](https://www.postgresql.org/docs/current/textsearch-intro.html).\nTo know more on how to use text search components check instructions for the [text module](/text).\nThe library is written in a java programming language.\nThe project for this moment supports Hibernate with version 5 and 6.\nThe required version of java is at least version 8 for hibernate 5 support and version 11 for hibernate 6.\n\n### Setting maven dependency\nThe project is available in the central maven repository.\nYou can use it just by adding it as a dependency in the project descriptor file (pom.xml).\n \n**For Hibernate 5:**\n```xml\n        \u003cdependency\u003e\n            \u003cgroupId\u003ecom.github.starnowski.posjsonhelper\u003c/groupId\u003e\n            \u003cartifactId\u003ehibernate5\u003c/artifactId\u003e\n            \u003cversion\u003e0.4.5\u003c/version\u003e\n        \u003c/dependency\u003e\n```\n\n**For Hibernate 6:**\n```xml\n        \u003cdependency\u003e\n            \u003cgroupId\u003ecom.github.starnowski.posjsonhelper\u003c/groupId\u003e\n            \u003cartifactId\u003ehibernate6\u003c/artifactId\u003e\n            \u003cversion\u003e0.4.5\u003c/version\u003e\n        \u003c/dependency\u003e\n```\n\n#### Optional dependencies\n\nThe posjsonhelper library does not have transient dependency to hibernate library.\nSo please bare in mind that hibernate dependency has to be added separetly in your project like below:\n\n```xml\n  \u003cdependency\u003e\n    \u003cgroupId\u003eorg.hibernate\u003c/groupId\u003e\n    \u003cartifactId\u003ehibernate-core\u003c/artifactId\u003e\n    \u003cversion\u003e????\u003c/version\u003e\n  \u003c/dependency\u003e\n```\n\nPlease check hibernate compatibility [version matrix](#hibernate-6-version-compatibility) to check correct version.\n\nDefault implementation for some functionalities related to the JSON operations require org.json:json library.\nHowever, there are ways to implements specific interfaces and below library might not be necessary to add.\n\n```xml\n  \u003cdependency\u003e\n    \u003cgroupId\u003eorg.json\u003c/groupId\u003e\n    \u003cartifactId\u003ejson\u003c/artifactId\u003e\n    \u003cversion\u003e20240303\u003c/version\u003e\n  \u003c/dependency\u003e\n```\n\n### Building project locally\nIf someone would like to build the project locally from the source please see the CONTRIBUTING.md file to check how to set up the project locally.\n\n### How to attach postgresql dialect\n\n**Important! This section is only valid for Hibernate 5.**\nTo be able to use the posjsonhelper library in the project there has to be specified correct hibernate dialect.\nLibrary implements few wrappers that extends already existed hibernate dialects for postgresql:\n- com.github.starnowski.posjsonhelper.hibernate5.dialects.PostgreSQL10DialectWrapper\n- com.github.starnowski.posjsonhelper.hibernate5.dialects.PostgreSQL95DialectWrapper\n\nDialect has to be set in hibernate configuration file for example:\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\" ?\u003e\n\u003chibernate-configuration xmlns=\"http://www.hibernate.org/xsd/orm/cfg\"\u003e\n    \u003csession-factory\u003e\n        \u003cproperty name=\"hibernate.dialect\"\u003ecom.github.starnowski.posjsonhelper.hibernate5.dialects.PostgreSQL95DialectWrapper\u003c/property\u003e\n...\n```\n\nor for example in spring framework configuration properties file:\n\n```properties\n...\nspring.jpa.properties.hibernate.dialect=com.github.starnowski.posjsonhelper.hibernate5.dialects.PostgreSQL95DialectWrapper\n...\n```\n\nIn case if you already have type that extends hibernate dialect type and it required for your project.\nYou add adjustment to your type so that it would use PostgreSQLDialectEnricher component.\n\n```java\nimport com.github.starnowski.posjsonhelper.hibernate5.PostgreSQLDialectEnricher;\nimport org.hibernate.dialect.PostgreSQL95Dialect;\n\npublic class PostgreSQLDialectWithDifferentSchema extends PostgreSQL95Dialect {\n\n    public PostgreSQLDialectWithDifferentSchema() {\n        PostgreSQLDialectEnricher enricher = new PostgreSQLDialectEnricher();\n        enricher.enrich(this);\n    }\n}\n\n```\n\n### How to attach FunctionContributor\n\n**Important! This section is only valid for Hibernate 6.**\nTo use the posjsonhelper library in the project that uses Hibernate 6, there must be a specified org.hibernate.boot.model.FunctionContributor implementation.\nLibrary has implementation of this interface, that is com.github.starnowski.posjsonhelper.hibernate6.PosjsonhelperFunctionContributor.\n\nTo use this implementation it is required to create file with name \"org.hibernate.boot.model.FunctionContributor\" under \"resources/META-INF/services\" directory.\n\nThe alternative solution is to use com.github.starnowski.posjsonhelper.hibernate6.SqmFunctionRegistryEnricher component during application start-up.\nLike in the below example with the usage of the Spring framework.\n\n```java\nimport com.github.starnowski.posjsonhelper.hibernate6.SqmFunctionRegistryEnricher;\nimport jakarta.persistence.EntityManager;\nimport org.hibernate.query.sqm.NodeBuilder;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.ApplicationListener;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.event.ContextRefreshedEvent;\n\n@Configuration\npublic class FunctionDescriptorConfiguration implements\n        ApplicationListener\u003cContextRefreshedEvent\u003e {\n\n    @Autowired\n    private EntityManager entityManager;\n\n    @Override\n    public void onApplicationEvent(ContextRefreshedEvent event) {\n        NodeBuilder nodeBuilder = (NodeBuilder) entityManager.getCriteriaBuilder();\n        SqmFunctionRegistryEnricher sqmFunctionRegistryEnricher = new SqmFunctionRegistryEnricher();\n        sqmFunctionRegistryEnricher.enrich(nodeBuilder.getQueryEngine().getSqmFunctionRegistry());\n    }\n}\n```\n\n### Apply DDL changes\n\nTo use the posjsonhelper library it is required to create a few SQL functions that execute JSON operators.\nSome JSON operators can not be executed by hibernate because they must be escaped.\nFor a default configuration, the library requires the below functions to be created.\n\n```sql\nCREATE OR REPLACE FUNCTION jsonb_all_array_strings_exist(jsonb, text[]) RETURNS boolean AS $$\nSELECT $1 ?\u0026 $2;\n$$ LANGUAGE SQL;\n\nCREATE OR REPLACE FUNCTION jsonb_any_array_strings_exist(jsonb, text[]) RETURNS boolean AS $$\nSELECT $1 ?| $2;\n$$ LANGUAGE SQL;\n```\n\nGenerated DDL statement can be executed during integration tests or used by tools that apply changes to the database, like [Liquibase](https://www.liquibase.org/) or [Flyway](https://flywaydb.org/).\n**Important!**\nIf there would be requirement to use similar function but with different names then this has to be specified in application [properties](#properties).\nIt is required because types extends hibernate dialect type, mentioned in the [\"how to attach postgresql dialect\"](#how-to-attach-postgresql dialect) section may not have access to application context (IoC).\nHowever, in case if such properties should be passed in different way then the PostgreSQLDialectEnricher type has also method to pass context objects (please check [Core context](#core-context) and [Hibernate Context](#hibernate-context))\n\n#### Core context\n\nContext class holds names of functions used by library.\nThe dialect classes use CoreContextPropertiesSupplier component that generates Context object based on system property.\n\n#### Apply DDL changes programmatically\n\nIt is posible also to add DDL programmatically by using DatabaseOperationExecutorFacade type.\nBelow there is example on how to apply DDL changes in application with Spring framework context.\n\n```java\nimport com.github.starnowski.posjsonhelper.core.Context;\nimport com.github.starnowski.posjsonhelper.core.DatabaseOperationExecutorFacade;\nimport com.github.starnowski.posjsonhelper.core.DatabaseOperationType;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.ApplicationListener;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.event.ContextRefreshedEvent;\n\nimport javax.sql.DataSource;\n\n@Configuration\npublic class SQLFunctionsConfiguration implements\n        ApplicationListener\u003cContextRefreshedEvent\u003e {\n\n    @Autowired\n    private Context context;\n    @Autowired\n    private DataSource dataSource;\n\n    @Override\n    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {\n        DatabaseOperationExecutorFacade facade = new DatabaseOperationExecutorFacade();\n        try {\n            facade.execute(dataSource, context, DatabaseOperationType.LOG_ALL);\n            facade.execute(dataSource, context, DatabaseOperationType.CREATE);\n            facade.execute(dataSource, context, DatabaseOperationType.VALIDATE);\n        } catch (Exception e) {\n            throw new RuntimeException(\"Error during initialization of sql functions for jsonb type operations\", e);\n        }\n    }\n}\n```\n\nThere are a few operations that can be executed by the DatabaseOperationExecutorFacade object\n\n| Property name |   Description    |\n|---------------|------------------|\n|CREATE         | Applies DDL changes to database |\n|VALIDATE       | Validates if DDL changes were applied to database |\n|DROP           | Drops DDL changes in database |\n|LOG_ALL        | Displays DDL scripts for CREATE, VALIDATE and DROP operations |\n\n### How to use query helper\n\nFor easier explanation let's assume that we have a database table with one column that stores jsonb type.\n\n```sql\ncreate table item (\n       id int8 not null,\n        jsonb_content jsonb,\n        primary key (id)\n    )\n```\n\nFor this table, we can insert row with any json, like in example below:\n\n```sql \nINSERT INTO item (id, jsonb_content) VALUES (1, '{\"top_element_with_set_of_values\":[\"TAG1\",\"TAG2\",\"TAG11\",\"TAG12\",\"TAG21\",\"TAG22\"]}');\nINSERT INTO item (id, jsonb_content) VALUES (2, '{\"top_element_with_set_of_values\":[\"TAG3\"]}');\n\n-- item without any properties, just an empty json\nINSERT INTO item (id, jsonb_content) VALUES (6, '{}');\n\n-- int values\nINSERT INTO item (id, jsonb_content) VALUES (7, '{\"integer_value\": 132}');\n\n-- double values\nINSERT INTO item (id, jsonb_content) VALUES (10, '{\"double_value\": 353.01}');\nINSERT INTO item (id, jsonb_content) VALUES (11, '{\"double_value\": -1137.98}');\n\n-- enum values\nINSERT INTO item (id, jsonb_content) VALUES (13, '{\"enum_value\": \"SUPER\"}');\n\n-- string values\nINSERT INTO item (id, jsonb_content) VALUES (18, '{\"string_value\": \"the end of records\"}');\n```\n\n#### Hibernate Context\n\nMost predicate components use Hibernate Context object.\nIt holds mostly the names of hibernate function names used in project.\nThe dialect classes and FunctionContributor type use HibernateContextPropertiesSupplier component that generates HibernateContext object based on system property.\nIf there is no need to change default HQL function names for psojsonhelper operators then it is even to use HibernateContext created by builder component like below:\n\n```java\n    HibernateContext hibernateContext = HibernateContext.builder().build();\n```\n\n#### JsonBExtractPath - jsonb_extract_path\n\nThe \"jsonb_extract_path\" is postgresql function that returns jsonb value pointed to by path elements passed as \"text[]\" (equivalent to #\u003e operator).\nIt is useful because a lot of functions use the \"jsonb\" type for execution.\nPlease check [postgresql documentation](https://www.postgresql.org/docs/10/functions-json.html) for more information.\n**Hibernate 5 example**:\nBelow there is an example of a method that returns a list of items object for which json content property \"top_element_with_set_of_values\" contains an exact set of values.\nThe example use [JsonbAllArrayStringsExistPredicate](#jsonballarraystringsexistpredicate).\n\n```java\n    @Autowired\n    private HibernateContext hibernateContext;\n    @Autowired\n    private EntityManager entityManager;\n\n    public List\u003cItem\u003e findAllByAllMatchingTags(Set\u003cString\u003e tags) {\n        CriteriaBuilder cb = entityManager.getCriteriaBuilder();\n        CriteriaQuery\u003cItem\u003e query = cb.createQuery(Item.class);\n        Root\u003cItem\u003e root = query.from(Item.class);\n        query.select(root);\n        query.where(new JsonbAllArrayStringsExistPredicate(hibernateContext, (CriteriaBuilderImpl) cb, new JsonBExtractPath((CriteriaBuilderImpl) cb, singletonList(\"top_element_with_set_of_values\"), root.get(\"jsonbContent\")), tags.toArray(new String[0])));\n        return entityManager.createQuery(query).getResultList();\n    }\n```\n\nFor the above method, Hibernate will execute the HQL query:\n\n```hql \nselect\n        generatedAlias0 \n    from\n        Item as generatedAlias0 \n    where\n        jsonb_all_array_strings_exist( jsonb_extract_path( generatedAlias0.jsonbContent , :param0 ) , json_function_json_array(:param1)) = TRUE\n```\n\nNative sql is going to have below form:\n\n```sql \nselect\n            item0_.id as id1_0_,\n            item0_.jsonb_content as jsonb_co2_0_ \n        from\n            item item0_ \n        where\n            jsonb_all_array_strings_exist(jsonb_extract_path(item0_.jsonb_content,?), array[?])=true\n```\n\nFor more details please check the [DAO](/hibernate5/src/test/java/com/github/starnowski/posjsonhelper/hibernate5/demo/dao/ItemDao.java) used in tests.\n\n**Hibernate 6 example**:\n\nBelow there is the same example as above but for Hibernate 6.\n\n```java\n\nimport org.hibernate.query.sqm.NodeBuilder;\n....\n    @Autowired\n    private HibernateContext hibernateContext;\n    @Autowired\n    private EntityManager entityManager;\n\n    public List\u003cItem\u003e findAllByAllMatchingTags(Set\u003cString\u003e tags) {\n        CriteriaBuilder cb = entityManager.getCriteriaBuilder();\n        CriteriaQuery\u003cItem\u003e query = cb.createQuery(Item.class);\n        Root\u003cItem\u003e root = query.from(Item.class);\n        query.select(root);\n        query.where(new JsonbAllArrayStringsExistPredicate(hibernateContext, (NodeBuilder) cb, new JsonBExtractPath(root.get(\"jsonbContent\"), (NodeBuilder) cb, singletonList(\"top_element_with_set_of_values\")), tags.toArray(new String[0])));\n        return entityManager.createQuery(query).getResultList();\n    }\n```\n\nFor more details please check the [DAO](/hibernate6-tests/hibernate6-tests-core/src/main/java/com/github/starnowski/posjsonhelper/hibernate6/demo/dao/ItemDao.java) used in tests.\n\n#### JsonBExtractPathText - jsonb_extract_path_text\n\nThe \"jsonb_extract_path_text\" is postgresql function that returns JSON value as text pointed to by path elements passed as \"text[]\" (equivalent to #\u003e\u003e operator).\nPlease check [postgresql documentation](https://www.postgresql.org/docs/10/functions-json.html) for more information.\nBelow there is an example for Hibernate 5 of a method that looks for items containing specific string values matched by the \"LIKE\" operator.\n\n```java\n    public List\u003cItem\u003e findAllByStringValueAndLikeOperator(String expression) {\n        CriteriaBuilder cb = entityManager.getCriteriaBuilder();\n        CriteriaQuery\u003cItem\u003e query = cb.createQuery(Item.class);\n        Root\u003cItem\u003e root = query.from(Item.class);\n        query.select(root);\n        query.where(cb.like(new JsonBExtractPathText((CriteriaBuilderImpl) cb, singletonList(\"string_value\"), root.get(\"jsonbContent\")), expression));\n        return entityManager.createQuery(query).getResultList();\n    }\n```\n\nFor the above method, Hibernate will execute the HQL query:\n\n```hql\nselect\n        generatedAlias0 \n    from\n        Item as generatedAlias0 \n    where\n        jsonb_extract_path_text( generatedAlias0.jsonbContent , :param0 ) like :param1\n```\nNative sql is going to have below form:\n\n```sql\nselect\n            item0_.id as id1_0_,\n            item0_.jsonb_content as jsonb_co2_0_ \n        from\n            item item0_ \n        where\n            jsonb_extract_path_text(item0_.jsonb_content,?) like ?\n```\n\nFor more details and examples with the IN operator or how to use numeric values please check the [DAO](/hibernate5/src/test/java/com/github/starnowski/posjsonhelper/hibernate5/demo/dao/ItemDao.java) used in tests.\n\n**Hibernate 6 example**:\n\nBelow there is the same example as above but for Hibernate 6.\n\n```java\n    ....\n    public List\u003cItem\u003e findAllByStringValueAndLikeOperator(String expression) {\n        CriteriaBuilder cb = entityManager.getCriteriaBuilder();\n        CriteriaQuery\u003cItem\u003e query = cb.createQuery(Item.class);\n        Root\u003cItem\u003e root = query.from(Item.class);\n        query.select(root);\n        query.where(cb.like(new JsonBExtractPathText(root.get(\"jsonbContent\"), singletonList(\"string_value\"), (NodeBuilder) cb), expression));\n        return entityManager.createQuery(query).getResultList();\n        }\n\n```\n\nFor more details please check the [DAO](/hibernate6-tests/hibernate6-tests-core/src/main/java/com/github/starnowski/posjsonhelper/hibernate6/demo/dao/ItemDao.java) used in tests.\n\n#### JsonbAllArrayStringsExistPredicate\n\nThe JsonbAllArrayStringsExistPredicate type represents predicate that checks if passed string arrays exist in json array property.\nFirst example for this predicate was introduce in [\"JsonBExtractPath - jsonb_extract_path\"](#jsonbextractpath---jsonb_extract_path) section.\nThese predicates assume that the SQL function with default name jsonb_all_array_strings_exist, mentioned in the section [\"Apply DDL changes\"](#apply-ddl-changes) exists.\nThe below example with a combination with the operator NOT presents items that do not have all searched strings.\n**Example valid for Hibernate 5 only!**\n\n```java\n    public List\u003cItem\u003e findAllThatDoNotMatchByAllMatchingTags(Set\u003cString\u003e tags) {\n        CriteriaBuilder cb = entityManager.getCriteriaBuilder();\n        CriteriaQuery\u003cItem\u003e query = cb.createQuery(Item.class);\n        Root\u003cItem\u003e root = query.from(Item.class);\n        query.select(root);\n        Predicate notAllMatchingTags = cb.not(new JsonbAllArrayStringsExistPredicate(hibernateContext, (CriteriaBuilderImpl) cb, new JsonBExtractPath((CriteriaBuilderImpl) cb, singletonList(\"top_element_with_set_of_values\"), root.get(\"jsonbContent\")), tags.toArray(new String[0])));\n        Predicate withoutSetOfValuesProperty = cb.isNull(new JsonBExtractPath((CriteriaBuilderImpl) cb, singletonList(\"top_element_with_set_of_values\"), root.get(\"jsonbContent\")));\n        query.where(cb.or(withoutSetOfValuesProperty, notAllMatchingTags));\n        return entityManager.createQuery(query).getResultList();\n    }\n```\n\nFor the above method, Hibernate will execute the HQL query:\n\n```hql\nselect\n        generatedAlias0 \n    from\n        Item as generatedAlias0 \n    where\n        (\n            jsonb_extract_path( generatedAlias0.jsonbContent , :param0 ) is null \n        ) \n        or (\n            jsonb_all_array_strings_exist( jsonb_extract_path( generatedAlias0.jsonbContent , :param1 ) , json_function_json_array(:param2, :param3)) = FALSE \n        )\n```\nNative sql is going to have below form:\n\n```sql\nselect\n            item0_.id as id1_0_,\n            item0_.jsonb_content as jsonb_co2_0_ \n        from\n            item item0_ \n        where\n            jsonb_extract_path(item0_.jsonb_content,?) is null \n            or jsonb_all_array_strings_exist(jsonb_extract_path(item0_.jsonb_content,?), array[?,?])=false\n```\n\n**Hibernate 6 example**:\n\nBelow there is the same example as above but for Hibernate 6.\n\n```java\n    public List\u003cItem\u003e findAllThatDoNotMatchByAllMatchingTags(Set\u003cString\u003e tags) {\n        CriteriaBuilder cb = entityManager.getCriteriaBuilder();\n        CriteriaQuery\u003cItem\u003e query = cb.createQuery(Item.class);\n        Root\u003cItem\u003e root = query.from(Item.class);\n        query.select(root);\n        Predicate notAllMatchingTags = cb.not(new JsonbAllArrayStringsExistPredicate(hibernateContext, (NodeBuilder) cb, new JsonBExtractPath(root.get(\"jsonbContent\"), (NodeBuilder) cb, singletonList(\"top_element_with_set_of_values\")), tags.toArray(new String[0])));\n        Predicate withoutSetOfValuesProperty = cb.isNull(new JsonBExtractPath(root.get(\"jsonbContent\"), (NodeBuilder) cb, singletonList(\"top_element_with_set_of_values\")));\n        query.where(cb.or(withoutSetOfValuesProperty, notAllMatchingTags));\n        return entityManager.createQuery(query).getResultList();\n    }\n```\n\nFor more details please check the [DAO](/hibernate6-tests/hibernate6-tests-core/src/main/java/com/github/starnowski/posjsonhelper/hibernate6/demo/dao/ItemDao.java) used in tests.\n\n#### JsonbAnyArrayStringsExistPredicate\n\nThe JsonbAnyArrayStringsExistPredicate type represents a predicate that checks if passed string arrays exist in json array property.\nThese predicates assume that the SQL function with default name jsonb_any_array_strings_exist, mentioned in the section [\"Apply DDL changes\"](#apply-ddl-changes) exists.\nBelow there is an example of a method that looks for all items that property that holds array contains at least one string passed from the array passed as method argument.\n**Example valid for Hibernate 5 only!**\n\n```java\n    public List\u003cItem\u003e findAllByAnyMatchingTags(HashSet\u003cString\u003e tags) {\n        CriteriaBuilder cb = entityManager.getCriteriaBuilder();\n        CriteriaQuery\u003cItem\u003e query = cb.createQuery(Item.class);\n        Root\u003cItem\u003e root = query.from(Item.class);\n        query.select(root);\n        query.where(new JsonbAnyArrayStringsExistPredicate(hibernateContext, (CriteriaBuilderImpl) cb, new JsonBExtractPath((CriteriaBuilderImpl) cb, singletonList(\"top_element_with_set_of_values\"), root.get(\"jsonbContent\")), tags.toArray(new String[0])));\n        return entityManager.createQuery(query).getResultList();\n    }\n```\n\nFor the above method, Hibernate will execute the HQL query:\n\n```hql\nselect\n        generatedAlias0 \n    from\n        Item as generatedAlias0 \n    where\n        jsonb_any_array_strings_exist( jsonb_extract_path( generatedAlias0.jsonbContent , :param0 ) , json_function_json_array(:param1, :param2)) = TRUE\n```\nNative sql is going to have below form:\n\n```sql\nselect\n            item0_.id as id1_0_,\n            item0_.jsonb_content as jsonb_co2_0_ \n        from\n            item item0_ \n        where\n            jsonb_any_array_strings_exist(jsonb_extract_path(item0_.jsonb_content,?), array[?,?])=true\n```\n**Hibernate 6 example**:\n\nBelow there is the same example as above but for Hibernate 6.\n\n```java\n\npublic List\u003cItem\u003e findAllByAnyMatchingTags(HashSet\u003cString\u003e tags) {\n        CriteriaBuilder cb = entityManager.getCriteriaBuilder();\n        CriteriaQuery\u003cItem\u003e query = cb.createQuery(Item.class);\n        Root\u003cItem\u003e root = query.from(Item.class);\n        query.select(root);\n        query.where(new JsonbAnyArrayStringsExistPredicate(hibernateContext, (NodeBuilder) cb, new JsonBExtractPath(root.get(\"jsonbContent\"), (NodeBuilder) cb, singletonList(\"top_element_with_set_of_values\")), tags.toArray(new String[0])));\n        return entityManager.createQuery(query).getResultList();\n        }\n\n```\n\nFor more details and examples with the IN operator or how to use numeric values please check the [DAO](/hibernate5/src/test/java/com/github/starnowski/posjsonhelper/hibernate5/demo/dao/ItemDao.java) used in tests.\n\n## Modify JSON\n\nThe library can also be used for JSON modification operations. By default, in Hibernate, we can always update a column with JSON content by setting its entire value.\nThe posjsonhelper library also allows you to modify JSON content by setting, replacing, or removing individual JSON properties without replacing its full content.\nThe library contains several JSON functions and operators that allow for this type of operation.\n\n### jsonb_set function wrapper\n\nWrapper for [jsonb_set](https://www.postgresql.org/docs/9.5/functions-json.html) function.\nThe function sets or replaces the value of the JSON property based on the JSON path. \nCheck out the following example of how it can be used with the CriteriaUpdate component:\n\n```java\n// GIVEN\n        Long itemId = 19L;\n        String property = \"birthday\";\n        String value = \"1970-01-01\";\n        String expectedJson = \"{\\\"child\\\": {\\\"pets\\\" : [\\\"dog\\\"], \\\"birthday\\\": \\\"1970-01-01\\\"}}\";\n        // when\n        CriteriaUpdate\u003cItem\u003e criteriaUpdate = entityManager.getCriteriaBuilder().createCriteriaUpdate(Item.class);\n        Root\u003cItem\u003e root = criteriaUpdate.from(Item.class);\n\n        // Set the property you want to update and the new value\n        criteriaUpdate.set(\"jsonbContent\", new JsonbSetFunction((NodeBuilder) entityManager.getCriteriaBuilder(), root.get(\"jsonbContent\"), new JsonTextArrayBuilder().append(\"child\").append(property).build().toString(), JSONObject.quote(value), hibernateContext));\n\n        // Add any conditions to restrict which entities will be updated\n        criteriaUpdate.where(entityManager.getCriteriaBuilder().equal(root.get(\"id\"), itemId));\n\n        // Execute the update\n        entityManager.createQuery(criteriaUpdate).executeUpdate();\n\n        // then\n        Item item = tested.findById(itemId);\n        assertThat((String) JsonPath.read(item.getJsonbContent(), \"$.child.\" + property)).isEqualTo(value);\n        JSONObject jsonObject = new JSONObject(expectedJson);\n        DocumentContext document = JsonPath.parse((Object) JsonPath.read(item.getJsonbContent(), \"$\"));\n        assertThat(document.jsonString()).isEqualTo(jsonObject.toString());\n```\n\nThis would generate the following SQL update statement:\n\n```sql\nupdate\n        item \n    set\n        jsonb_content=jsonb_set(jsonb_content, ?::text[], ?::jsonb) \n    where\n        id=?\nHibernate: \n    select\n        i1_0.id,\n        i1_0.jsonb_content \n    from\n        item i1_0 \n    where\n        i1_0.id=?\n```\n\nThe function can also be used in HQL statements, as in the following example:\n\n```java\n    @Transactional\n    public void updateJsonBySettingPropertyForItemByHQL(Long itemId, String property, String value) {\n        // Execute the update\n        String hqlUpdate = \"UPDATE Item SET jsonbContent = jsonb_set(jsonbContent, %s(:path, 'text[]'), %s(:json, 'jsonb' ) ) WHERE id = :id\".formatted(hibernateContext.getCastFunctionOperator(), hibernateContext.getCastFunctionOperator());\n        int updatedEntities = entityManager.createQuery( hqlUpdate )\n                .setParameter(\"id\", itemId)\n                .setParameter(\"path\", new JsonTextArrayBuilder().append(\"child\").append(property).build().toString())\n                .setParameter(\"json\", JSONObject.quote(value))\n                .executeUpdate();\n    }\n```\n\n### Concatenation operator wrapper '||'\n\nWrapper for [concatenation operator](https://www.postgresql.org/docs/9.5/functions-json.html).\nThe wrapper concatenate two jsonb values into a new jsonb value.\nCheck out the following example of how it can be used with the CriteriaUpdate component:\n\n```java\n        // GIVEN\n        Long itemId = 19l;\n        String property = \"birthday\";\n        String value = \"1970-01-01\";\n\n        // WHEN\n        CriteriaUpdate\u003cItem\u003e criteriaUpdate = entityManager.getCriteriaBuilder().createCriteriaUpdate(Item.class);\n        Root\u003cItem\u003e root = criteriaUpdate.from(Item.class);\n\n        JSONObject jsonObject = new JSONObject();\n        jsonObject.put(\"child\", new JSONObject());\n        jsonObject.getJSONObject(\"child\").put(property, value);\n        criteriaUpdate.set(\"jsonbContent\", new ConcatenateJsonbOperator((NodeBuilder) entityManager.getCriteriaBuilder(), root.get(\"jsonbContent\"), jsonObject.toString(), hibernateContext));\n\n        criteriaUpdate.where(entityManager.getCriteriaBuilder().equal(root.get(\"id\"), itemId));\n\n        entityManager.createQuery(criteriaUpdate).executeUpdate();\n\n        // THEN\n        Item item = tested.findById(itemId);\n        assertThat((String) JsonPath.read(item.getJsonbContent(), \"$.child.\" + property)).isEqualTo(value);\n        JSONObject expectedJsonObject = new JSONObject().put(property, value);\n        DocumentContext document = JsonPath.parse((Object) JsonPath.read(item.getJsonbContent(), \"$.child\"));\n        assertThat(document.jsonString()).isEqualTo(expectedJsonObject.toString());\n```\n\nThis would generate the following SQL update statement:\n\n```sql\nupdate\n        item \n    set\n        jsonb_content=jsonb_content || ?::jsonb \n    where\n        id=?\nHibernate: \n    select\n        i1_0.id,\n        i1_0.jsonb_content \n    from\n        item i1_0 \n    where\n        i1_0.id=?\n```\n\nThe function can also be used in HQL statements, as in the following example:\n\n```java\n    @Transactional\n    public void updateJsonPropertyForItemByHQL(Long itemId, String property, String value) throws JSONException {\n        JSONObject jsonObject = new JSONObject();\n        jsonObject.put(\"child\", new JSONObject());\n        jsonObject.getJSONObject(\"child\").put(property, value);\n        String hqlUpdate = \"UPDATE Item SET jsonbContent = %s(jsonbContent, %s(:json, 'jsonb' ) ) WHERE id = :id\".formatted(hibernateContext.getConcatenateJsonbOperator(), hibernateContext.getCastFunctionOperator());\n        int updatedEntities = entityManager.createQuery( hqlUpdate )\n                .setParameter(\"id\", itemId)\n                .setParameter(\"json\", jsonObject.toString())\n                .executeUpdate();\n    }\n```\n\n### Delete the field or array element based on the index at the specified path '#-'\n\nWrapper for [deletes operator '#-'](https://www.postgresql.org/docs/9.5/functions-json.html).\nThe wrapper deletes the field or array element based on the index at the specified path, where path elements can be either field keys or array indexes.\nCheck out the following example of how it can be used with the CriteriaUpdate component:\n\n```java\n        // GIVEN\n        Item item = tested.findById(19L);\n        JSONObject jsonObject = new JSONObject(\"{\\\"child\\\": {\\\"pets\\\" : [\\\"dog\\\"]}}\");\n        DocumentContext document = JsonPath.parse((Object) JsonPath.read(item.getJsonbContent(), \"$\"));\n        assertThat(document.jsonString()).isEqualTo(jsonObject.toString());\n\n        // WHEN\n        CriteriaUpdate\u003cItem\u003e criteriaUpdate = entityManager.getCriteriaBuilder().createCriteriaUpdate(Item.class);\n        Root\u003cItem\u003e root = criteriaUpdate.from(Item.class);\n\n        // Set the property you want to update and the new value\n        criteriaUpdate.set(\"jsonbContent\", new DeleteJsonbBySpecifiedPathOperator((NodeBuilder) entityManager.getCriteriaBuilder(), root.get(\"jsonbContent\"), new JsonTextArrayBuilder().append(\"child\").append(\"pets\").build().toString(), hibernateContext));\n\n        // Add any conditions to restrict which entities will be updated\n        criteriaUpdate.where(entityManager.getCriteriaBuilder().equal(root.get(\"id\"), 19L));\n\n        // Execute the update\n        entityManager.createQuery(criteriaUpdate).executeUpdate();\n\n        // THEN\n        entityManager.refresh(item);\n        jsonObject = new JSONObject(\"{\\\"child\\\": {}}\");\n        document = JsonPath.parse((Object) JsonPath.read(item.getJsonbContent(), \"$\"));\n        assertThat(document.jsonString()).isEqualTo(jsonObject.toString());\n```\n\nThis would generate the following SQL update statement:\n\n```sql\nupdate\n        item \n    set\n        jsonb_content=(jsonb_content #- ?::text[]) \n    where\n        id=?\n```\n\nThe function can also be used in HQL statements, as in the following example:\n\n```java\n    @Transactional\n    public void updateJsonByDeletingSpecificPropertyForItemByHql(Long itemId, String property) {\n        // Execute the update\n        String hqlUpdate = \"UPDATE Item SET jsonbContent = %s(jsonbContent, %s(:path, 'text[]') ) WHERE id = :id\".formatted(hibernateContext.getDeleteJsonBySpecificPathOperator(), hibernateContext.getCastFunctionOperator());\n        int updatedEntities = entityManager.createQuery(hqlUpdate)\n                .setParameter(\"id\", itemId)\n                .setParameter(\"path\", new JsonTextArrayBuilder().append(\"child\").append(property).build().toString())\n                .executeUpdate();\n    }\n```\n\n### Delete a multiple array elements at the specified path '#-'\n\nThe RemoveJsonValuesFromJsonArrayFunction type is a hibernate operator that invokes the SQL function generated by the posjsonhelper library.\nBy default, the generated function looks like the below example:\n\n```sql\nCREATE OR REPLACE FUNCTION {{schema}}.remove_values_from_json_array(input_json jsonb, values_to_remove jsonb) RETURNS jsonb AS $$\nDECLARE\n    result jsonb;\nBEGIN\n    IF jsonb_typeof(values_to_remove) \u003c\u003e 'array' THEN\n        RAISE EXCEPTION 'values_to_remove must be a JSON array';\n    END IF;\n\n    result := (\n        SELECT jsonb_agg(element)\n        FROM jsonb_array_elements(input_json) AS element\n        WHERE NOT (element IN (SELECT jsonb_array_elements(values_to_remove)))\n    );\n\n    RETURN COALESCE(result, '[]'::jsonb);\nEND;\n$$ LANGUAGE plpgsql;\n```\n\nThe function has two input parameters. First is the JSON array, which is a base array for the result that the function will return.\nThe second parameter is also a JSON array that represents an element that should be removed from the result array.\nBelow is a code example of how this function can be used with another operator to update JSON columns with the SQL update statement.\n\n```java\n// GIVEN\n        Item item = tested.findById(24L);\n        DocumentContext document = JsonPath.parse((Object) JsonPath.read(item.getJsonbContent(), \"$\"));\n        assertThat(document.jsonString()).isEqualTo(\"{\\\"child\\\":{\\\"pets\\\":[\\\"crab\\\",\\\"chameleon\\\"]},\\\"inventory\\\":[\\\"mask\\\",\\\"fins\\\",\\\"compass\\\"]}\");\n        CriteriaUpdate\u003cItem\u003e criteriaUpdate = entityManager.getCriteriaBuilder().createCriteriaUpdate(Item.class);\n        Root\u003cItem\u003e root = criteriaUpdate.from(Item.class);\n\n        NodeBuilder nodeBuilder = (NodeBuilder) entityManager.getCriteriaBuilder();\n        JSONArray toRemoveJSONArray = new JSONArray(Arrays.asList(\"mask\", \"compass\"));\n        RemoveJsonValuesFromJsonArrayFunction deleteOperator = new RemoveJsonValuesFromJsonArrayFunction(nodeBuilder, new JsonBExtractPath(root.get(\"jsonbContent\"), nodeBuilder, Arrays.asList(\"inventory\")), toRemoveJSONArray.toString(), hibernateContext);\n        JsonbSetFunction jsonbSetFunction = new JsonbSetFunction(nodeBuilder, (SqmTypedNode) root.get(\"jsonbContent\"), new JsonTextArrayBuilder().append(\"inventory\").build().toString(), deleteOperator, hibernateContext);\n        // Set the property you want to update and the new value\n        criteriaUpdate.set(\"jsonbContent\", jsonbSetFunction);\n\n        // Add any conditions to restrict which entities will be updated\n        criteriaUpdate.where(entityManager.getCriteriaBuilder().equal(root.get(\"id\"), 24L));\n\n        // WHEN\n        entityManager.createQuery(criteriaUpdate).executeUpdate();\n\n        // THEN\n        entityManager.refresh(item);\n        document = JsonPath.parse((Object) JsonPath.read(item.getJsonbContent(), \"$\"));\n        assertThat(document.jsonString()).isEqualTo(\"{\\\"child\\\":{\\\"pets\\\":[\\\"crab\\\",\\\"chameleon\\\"]},\\\"inventory\\\":[\\\"fins\\\"]}\");\n```\n\nThe same example but with HQL query example:\n\n```java\n        // GIVEN\n        Item item = tested.findById(24L);\n        DocumentContext document = JsonPath.parse((Object) JsonPath.read(item.getJsonbContent(), \"$\"));\n        assertThat(document.jsonString()).isEqualTo(\"{\\\"child\\\":{\\\"pets\\\":[\\\"crab\\\",\\\"chameleon\\\"]},\\\"inventory\\\":[\\\"mask\\\",\\\"fins\\\",\\\"compass\\\"]}\");\n        CriteriaUpdate\u003cItem\u003e criteriaUpdate = entityManager.getCriteriaBuilder().createCriteriaUpdate(Item.class);\n        Root\u003cItem\u003e root = criteriaUpdate.from(Item.class);\n\n        JSONArray toRemoveJSONArray = new JSONArray(Arrays.asList(\"mask\", \"compass\"));\n        String hqlUpdate = \"UPDATE Item SET jsonbContent = %s(jsonbContent, %s(:path, 'text[]'), %s(jsonb_extract_path( jsonbContent , 'inventory' ), %s(:to_remove, 'jsonb')) ) WHERE id = :id\".formatted(JSONB_SET_FUNCTION_NAME, hibernateContext.getCastFunctionOperator(), hibernateContext.getRemoveJsonValuesFromJsonArrayFunction(), hibernateContext.getCastFunctionOperator());\n\n        // WHEN\n        entityManager.createQuery(hqlUpdate)\n                .setParameter(\"id\", 24L)\n                .setParameter(\"path\", new JsonTextArrayBuilder().append(\"inventory\").build().toString())\n                .setParameter(\"to_remove\", toRemoveJSONArray.toString())\n                .executeUpdate();\n\n        // THEN\n        entityManager.refresh(item);\n        document = JsonPath.parse((Object) JsonPath.read(item.getJsonbContent(), \"$\"));\n        assertThat(document.jsonString()).isEqualTo(\"{\\\"child\\\":{\\\"pets\\\":[\\\"crab\\\",\\\"chameleon\\\"]},\\\"inventory\\\":[\\\"fins\\\"]}\");\n```\n\nThose two examples are going to generate below SQL statement:\n\n```sql\nupdate\n        item \n    set\n        jsonb_content=jsonb_set(jsonb_content, ?::text[], remove_values_from_json_array(jsonb_extract_path(jsonb_content, ?), ?::jsonb)) \n    where\n        id=?\n```\n\n### Hibernate6JsonUpdateStatementBuilder - How to combine multiple modification operations with one update statement?\n\nUsing a single jsonb_set function to set a single property for JSON with a single update statement can be useful,\nhowever, it may be more useful to be able to set multiple properties at different levels of the JSON tree with a single update statement.\n\nLest check below code example:\n\n```java\n        // GIVEN\n        Item item = tested.findById(23L);\n                DocumentContext document = JsonPath.parse((Object) JsonPath.read(item.getJsonbContent(), \"$\"));\n                assertThat(document.jsonString()).isEqualTo(\"{\\\"child\\\":{\\\"pets\\\":[\\\"dog\\\"]},\\\"inventory\\\":[\\\"mask\\\",\\\"fins\\\"],\\\"nicknames\\\":{\\\"school\\\":\\\"bambo\\\",\\\"childhood\\\":\\\"bob\\\"}}\");\n                CriteriaUpdate\u003cItem\u003e criteriaUpdate = entityManager.getCriteriaBuilder().createCriteriaUpdate(Item.class);\n        Root\u003cItem\u003e root = criteriaUpdate.from(Item.class);\n\n        Hibernate6JsonUpdateStatementBuilder hibernate6JsonUpdateStatementBuilder = new Hibernate6JsonUpdateStatementBuilder(root.get(\"jsonbContent\"), (NodeBuilder) entityManager.getCriteriaBuilder(), hibernateContext);\n        hibernate6JsonUpdateStatementBuilder.appendJsonbSet(new JsonTextArrayBuilder().append(\"child\").append(\"birthday\").build(), quote(\"2021-11-23\"));\n        hibernate6JsonUpdateStatementBuilder.appendJsonbSet(new JsonTextArrayBuilder().append(\"child\").append(\"pets\").build(), \"[\\\"cat\\\"]\");\n        hibernate6JsonUpdateStatementBuilder.appendDeleteBySpecificPath(new JsonTextArrayBuilder().append(\"inventory\").append(\"0\").build());\n        hibernate6JsonUpdateStatementBuilder.appendJsonbSet(new JsonTextArrayBuilder().append(\"parents\").append(0).build(), \"{\\\"type\\\":\\\"mom\\\", \\\"name\\\":\\\"simone\\\"}\");\n        hibernate6JsonUpdateStatementBuilder.appendJsonbSet(new JsonTextArrayBuilder().append(\"parents\").build(), \"[]\");\n        hibernate6JsonUpdateStatementBuilder.appendDeleteBySpecificPath(new JsonTextArrayBuilder().append(\"nicknames\").append(\"childhood\").build());\n\n        // Set the property you want to update and the new value\n        criteriaUpdate.set(\"jsonbContent\", hibernate6JsonUpdateStatementBuilder.build());\n\n        // Add any conditions to restrict which entities will be updated\n        criteriaUpdate.where(entityManager.getCriteriaBuilder().equal(root.get(\"id\"), 23L));\n\n        // WHEN\n        entityManager.createQuery(criteriaUpdate).executeUpdate();\n\n        // THEN\n        entityManager.refresh(item);\n        document = JsonPath.parse((Object) JsonPath.read(item.getJsonbContent(), \"$\"));\n        assertThat(document.jsonString()).isEqualTo(\"{\\\"child\\\":{\\\"pets\\\":[\\\"cat\\\"],\\\"birthday\\\":\\\"2021-11-23\\\"},\\\"parents\\\":[{\\\"name\\\":\\\"simone\\\",\\\"type\\\":\\\"mom\\\"}],\\\"inventory\\\":[\\\"fins\\\"],\\\"nicknames\\\":{\\\"school\\\":\\\"bambo\\\"}}\");\n```\n\nIn the above code, we want to set three JSON properties \"child.birthday\", \"child.pets\" and \"parents\" and delete two others, \"inventory.0\" and \"nicknames.childhood\".\nThe \"parents\" property is new property that suppose to be an array.\nAlthough the setting new array property with some values could be done with single operation, however for demonstration purpose we use two operations.\nOne is for setting new property called \"parents\" with empty json array as value.\nAnd another operation that set element of an array at specific index.\n**If higher property does not exist then it has to be created before inner properties.**\nFortunately, the default instance of the Hibernate6JsonUpdateStatementBuilder type has appropriate sorting and filtering components to help you set the right order of operations.\nSo it doesn't matter whether we add the add-array-element operation before or after adding the create-array operation.\nBy default, operations that delete content will be added before those which add or replace content.\nOf course, it is possible to disable this behavior by setting these components to null.\nFor more details please check javadoc for Hibernate6JsonUpdateStatementBuilder type.\n\nThis code generates below SQL statement:\n\n```sql\nupdate\n        item \n    set\n        jsonb_content=\n        jsonb_set(\n          jsonb_set(\n            jsonb_set(\n              jsonb_set(\n                (\n                  (jsonb_content #- ?::text[]) -- the most nested #- operator\n                 #- ?::text[])\n              , ?::text[], ?::jsonb) -- the most nested jsonb_set operation\n            , ?::text[], ?::jsonb)\n          , ?::text[], ?::jsonb)\n        , ?::text[], ?::jsonb) \n    where\n        id=?\n```\n\nThe most inner jsonb_set function execution for this prepared statement is going to set an empty array for the \"parents\" property.\n\nThe builder has methods for setting values:\n\n- appendJsonbSet(JsonTextArray jsonTextArray, String value)\n- appendJsonbSet(JsonTextArray jsonTextArray, String value, C customValue)\n\nremoving properties:\n\n  appendDeleteBySpecificPath(JsonTextArray jsonTextArray)\n\nadding array elements\n\n- appendAddArrayItems(JsonTextArray jsonTextArray, String jsonArrayString)\n- appendAddArrayItems(JsonTextArray jsonTextArray, Collection\u003c?\u003e collection) ** Check comment about optional dependency!**\n\nremoving array elements\n\n- appendRemoveArrayItems(JsonTextArray jsonTextArray, String jsonArrayString)\n- appendRemoveArrayItems(JsonTextArray jsonTextArray, Collection\u003c?\u003e collection) ** Check comment about optional dependency!**\n\nSome methods related to modification on json array by default requires org.json.json library (check [optional dependencies](#optional-dependencies)).\nHowever, it is possible to pass custom implementation of interface that maps collection object to json array value with \"withCollectionToJsonArrayStringMapper(com.github.starnowski.posjsonhelper.hibernate6.Hibernate6JsonUpdateStatementBuilder.CollectionToJsonArrayStringMapper)\" builder method   \n\n#### How to add custom value support for Hibernate6JsonUpdateStatementBuilder?\n\nThe Hibernate6JsonUpdateStatementBuilder type is generic. A second generic type is a custom value that can be added to the Hibernate6JsonUpdateStatementBuilder context.\nBelow is a code example whose type represents array operations (elements that should be added to and removed from an array).\n\nCustom value type:\n\n```java\n    private static class JsonArrayOperations {\n\n        private final List\u003cString\u003e toDelete;\n        private final List\u003cString\u003e toAdd;\n\n        public JsonArrayOperations(List\u003cString\u003e toDelete, List\u003cString\u003e toAdd) {\n            this.toDelete = toDelete;\n            this.toAdd = toAdd;\n        }\n\n        public List\u003cString\u003e getToDelete() {\n            return toDelete;\n        }\n\n        public List\u003cString\u003e getToAdd() {\n            return toAdd;\n        }\n    }\n```\n\nUsage example:\n\n```java\n// GIVEN\n        Item item = tested.findById(24L);\n        DocumentContext document = JsonPath.parse((Object) JsonPath.read(item.getJsonbContent(), \"$\"));\n        assertThat(document.jsonString()).isEqualTo(\"{\\\"child\\\":{\\\"pets\\\":[\\\"crab\\\",\\\"chameleon\\\"]},\\\"inventory\\\":[\\\"mask\\\",\\\"fins\\\",\\\"compass\\\"]}\");\n        CriteriaUpdate\u003cItem\u003e criteriaUpdate = entityManager.getCriteriaBuilder().createCriteriaUpdate(Item.class);\n        Root\u003cItem\u003e root = criteriaUpdate.from(Item.class);\n\n        Hibernate6JsonUpdateStatementBuilder\u003cObject, JsonArrayOperations\u003e hibernate6JsonUpdateStatementBuilder = new Hibernate6JsonUpdateStatementBuilder(root.get(\"jsonbContent\"), (NodeBuilder) entityManager.getCriteriaBuilder(), hibernateContext);\n        hibernate6JsonUpdateStatementBuilder.appendJsonbSet(new JsonTextArrayBuilder().append(\"child\").append(\"pets\").build(), null, new JsonArrayOperations(Arrays.asList(\"crab\", \"ant\"), Arrays.asList(\"lion\", \"dolphin\")));\n        hibernate6JsonUpdateStatementBuilder.appendJsonbSet(new JsonTextArrayBuilder().append(\"name\").build(), JSONObject.quote(\"Simon\"));\n        hibernate6JsonUpdateStatementBuilder.appendJsonbSet(new JsonTextArrayBuilder().append(\"inventory\").build(), null, new JsonArrayOperations(Arrays.asList(\"compass\", \"mask\"), Arrays.asList(\"knife\")));\n        hibernate6JsonUpdateStatementBuilder.withJsonbSetFunctionFactory(new Hibernate6JsonUpdateStatementBuilder.DefaultJsonbSetFunctionFactory\u003cObject, JsonArrayOperations\u003e() {\n\n            public JsonbSetFunction build(NodeBuilder nodeBuilder, Path\u003cObject\u003e rootPath, JsonUpdateStatementConfiguration.JsonUpdateStatementOperation\u003cJsonArrayOperations\u003e operation, HibernateContext hibernateContext) {\n                if (operation.getCustomValue() != null) {\n                    JSONArray toAddJSONArray = new JSONArray(operation.getCustomValue().getToAdd());\n                    ConcatenateJsonbOperator concatenateOperator = new ConcatenateJsonbOperator(nodeBuilder, new JsonBExtractPath(rootPath, nodeBuilder, operation.getJsonTextArray().getPath().stream().map(ob -\u003e ob.toString()).collect(Collectors.toList())), toAddJSONArray.toString(), hibernateContext);\n                    JSONArray toRemoveJSONArray = new JSONArray(operation.getCustomValue().getToDelete());\n                    RemoveJsonValuesFromJsonArrayFunction deleteOperator = new RemoveJsonValuesFromJsonArrayFunction(nodeBuilder, concatenateOperator, toRemoveJSONArray.toString(), hibernateContext);\n                    return new JsonbSetFunction(nodeBuilder, (SqmTypedNode) rootPath, operation.getJsonTextArray().toString(), deleteOperator, hibernateContext);\n                } else {\n                    return super.build(nodeBuilder, rootPath, operation, hibernateContext);\n                }\n            }\n\n            @Override\n            public JsonbSetFunction build(NodeBuilder nodeBuilder, SqmTypedNode sqmTypedNode, JsonUpdateStatementConfiguration.JsonUpdateStatementOperation\u003cJsonArrayOperations\u003e operation, HibernateContext hibernateContext) {\n                if (operation.getCustomValue() != null) {\n                    JSONArray toAddJSONArray = new JSONArray(operation.getCustomValue().getToAdd());\n                    ConcatenateJsonbOperator concatenateOperator = new ConcatenateJsonbOperator(nodeBuilder, new JsonBExtractPath(root.get(\"jsonbContent\"), nodeBuilder, operation.getJsonTextArray().getPath().stream().map(ob -\u003e ob.toString()).collect(Collectors.toList())), toAddJSONArray.toString(), hibernateContext);\n                    JSONArray toRemoveJSONArray = new JSONArray(operation.getCustomValue().getToDelete());\n                    RemoveJsonValuesFromJsonArrayFunction deleteOperator = new RemoveJsonValuesFromJsonArrayFunction(nodeBuilder, concatenateOperator, toRemoveJSONArray.toString(), hibernateContext);\n                    return new JsonbSetFunction(nodeBuilder, sqmTypedNode, operation.getJsonTextArray().toString(), deleteOperator, hibernateContext);\n                } else {\n                    return super.build(nodeBuilder, sqmTypedNode, operation, hibernateContext);\n                }\n            }\n        });\n        // Set the property you want to update and the new value\n        criteriaUpdate.set(\"jsonbContent\", hibernate6JsonUpdateStatementBuilder.build());\n\n        // Add any conditions to restrict which entities will be updated\n        criteriaUpdate.where(entityManager.getCriteriaBuilder().equal(root.get(\"id\"), 24L));\n\n        // WHEN\n        entityManager.createQuery(criteriaUpdate).executeUpdate();\n\n        // THEN\n        entityManager.refresh(item);\n        document = JsonPath.parse((Object) JsonPath.read(item.getJsonbContent(), \"$\"));\n        assertThat(document.jsonString()).isEqualTo(\"{\\\"name\\\":\\\"Simon\\\",\\\"child\\\":{\\\"pets\\\":[\\\"chameleon\\\",\\\"lion\\\",\\\"dolphin\\\"]},\\\"inventory\\\":[\\\"fins\\\",\\\"knife\\\"]}\");\n```\n\n### Properties\n\n| Property name                                                                                   | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |\n|-------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| com.github.starnowski.posjsonhelper.core.functions.jsonb_all_array_strings_exist                | Name of SQL function that checks if all passed elements as the text[] exist in the JSON array property. By default, the name is the jsonb_all_array_strings_exist                                                                                                                                                                                                                                                                                                                                                           |\n| com.github.starnowski.posjsonhelper.core.functions.jsonb_any_array_strings_exist                | Name of SQL function that checks if any passed elements as the text[] exist in the JSON array property. By default, the name is the jsonb_any_array_strings_exist                                                                                                                                                                                                                                                                                                                                                           |\n| com.github.starnowski.posjsonhelper.core.functions.remove_values_from_json_array                | Name of SQL function that return jsonb array by deleting elements from jsonb array passed as input for function. By default, the name is the remove_values_from_json_array                                                                                                                                                                                                                                                                                                                                                  |\n| com.github.starnowski.posjsonhelper.core.schema                                                 | Name of database schema where the SQL functions should be created                                                                                                                                                                                                                                                                                                                                                                                                                                                           |\n| com.github.starnowski.posjsonhelper.core.hibernate.functions.jsonb_all_array_strings_exist      | Name of HQL function that invokes SQL function specified by the com.github.starnowski.posjsonhelper.core.functions.jsonb_all_array_strings_exist property. By default, the name is the jsonb_all_array_strings_exist                                                                                                                                                                                                                                                                                                        |\n| com.github.starnowski.posjsonhelper.core.hibernate.functions.jsonb_any_array_strings_exist      | Name of HQL function that invokes SQL function specified by the com.github.starnowski.posjsonhelper.core.functions.jsonb_any_array_strings_exist property. By default, the name is the jsonb_any_array_strings_exist                                                                                                                                                                                                                                                                                                        |\n| com.github.starnowski.posjsonhelper.core.hibernate.functions.json_function_json_array           | Name of HQL function that wraps the array operator in Postgresql. By default, the name is the json_function_json_array                                                                                                                                                                                                                                                                                                                                                                                                      |\n| com.github.starnowski.posjsonhelper.core.hibernate.functions.remove_values_from_json_array      | Name of HQL function that wraps function that return jsonb array by deleting elements from jsonb array passed as input for function. By default, the name is the remove_values_from_json_array                                                                                                                                                                                                                                                                                                                                                                                                                   |\n| com.github.starnowski.posjsonhelper.core.hibernate.functions.sqldefinitioncontextfactory.types  | System property that stores list of com.github.starnowski.posjsonhelper.core.sql.ISQLDefinitionContextFactory types that should be loaded. Instead of loading types that can be found on the classpath for package \"com.github.starnowski.posjsonhelper\". Types on the list are separated by comma character \".\".                                                                                                                                                                                                           |\n| com.github.starnowski.posjsonhelper.hibernate6.functiondescriptorregisterfactory.types          | (Used only in Hibernate 6) System property that stores list of com.github.starnowski.posjsonhelper.hibernate6.descriptor.FunctionDescriptorRegisterFactoriesSupplier types that should be loaded. Instead of loading types that can be found on the classpath for package \"com.github.starnowski.posjsonhelper\". Types on the list are separated by comma character \".\".                                                                                                                                                    |\n| com.github.starnowski.posjsonhelper.hibernate6.functiondescriptorregisterfactory.types.excluded | (Used only in Hibernate 6) System property that stores list of com.github.starnowski.posjsonhelper.hibernate6.descriptor.FunctionDescriptorRegisterFactoriesSupplier types that should be excluded from loading. If \"com.github.starnowski.posjsonhelper.hibernate6.functiondescriptorregisterfactory.types\" property is also specified then \"com.github.starnowski.posjsonhelper.hibernate6.functiondescriptorregisterfactory.types.excluded\" has higher priority. Types on the list are separated by comma character \".\". |\n\n### Hibernate 6 version compatibility\n\nCompatibility matrix with Hibernate 6.  \n\n| Posjsonhelper | Hibernate 6 |\n|---------------|-------------|\n| 0.3.0         | 6.4.0.Final |\n| 0.2.0 - 0.2.1 | 6.1.5.Final |\n\n# Known issues\n  * **Problem with hibernate package, version or classes etc.**\n\n    If you face issue related to missing method definition or type like for example:\n      ```\n        java.lang.NoSuchMethodError: 'org.hibernate.query.criteria.JpaExpression\n      ```\n    Then first please check if your project has hibernate-core library on classpath.\n    The hibernate-core is [optional dependency](#optional-dependencies) for this project and you have to make sure that it was added in your project.\n    Please check similar issue [145](https://github.com/starnowski/posjsonhelper/issues/145).\n    If you hibernate-core is on classpath and the issue still exists then please [report issue](#reporting-issues).\n\n# Reporting issues\n* Any new issues please report in [GitHub site](https://github.com/starnowski/posjsonhelper/issues)\n\n# Project contribution\n* Look for open issues or create your own\n* Fork repository on Github and start applying your changes to master branch or release branch\n* Follow CONTRIBUTING.md document for coding rules\n* Create pull request\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstarnowski%2Fposjsonhelper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstarnowski%2Fposjsonhelper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstarnowski%2Fposjsonhelper/lists"}