{
  "id": "write-behind",
  "title": "Write-behind, write-through, and read-through caching",
  "url": "https://redis.io/docs/latest/operate/oss_and_stack/stack-with-enterprise/deprecated-features/gears-v1/jvm/recipes/write-behind/",
  "summary": "Write-behind, write-through, and read-through caching between Redis and other databases (SQL or NoSQL).",
  "tags": [
    "docs",
    "operate",
    "stack"
  ],
  "last_updated": "2026-04-22T11:55:45+02:00",
  "page_type": "content",
  "content_hash": "67dfb73e0a945873908daa05667922a604f062c99bed361c0891e5857a13ad2c",
  "sections": [
    {
      "id": "overview",
      "title": "Overview",
      "role": "overview",
      "text": "The [rghibernate](https://github.com/RedisGears/rghibernate) recipe uses RedisGears functions and the [Hibernate](https://hibernate.org/) framework to implement write-behind, write-through, and read-through caching.\n\nThese caching strategies allow applications to simply connect to a Redis cache layer instead of an underlying database. Whenever the application updates data in the cache, Redis also syncs the data in the backend database.\n\nThe underlying database could be an SQL database like MySQL, so you will need to provide an XML file that tells rghibernate how to map data between Redis and the other database."
    },
    {
      "id": "differences-from-rgsync",
      "title": "Differences from RGSync",
      "role": "content",
      "text": "[RGSync](https://github.com/RedisGears/rgsync):\n- Python-based recipe\n- Programmable\n\n[rghibernate](https://github.com/RedisGears/rghibernate):\n- Java-based recipe\n- Uses the Hibernate framework\n- Configurable rather than programmable"
    },
    {
      "id": "set-up-write-behind-and-read-through",
      "title": "Set up write-behind and read-through",
      "role": "content",
      "text": "To set up write-behind caching, first build an rghibernate JAR and register it with RedisGears.\n\nThen, register the following configuration files:\n\n- Connector XML: Tells Redis how to connect to the underlying database.\n\n- Mapping XML: Shows how to map data between the two databases, such as mapping Redis hashes to MySQL tables."
    },
    {
      "id": "register-rghibernate-jar",
      "title": "Register rghibernate JAR",
      "role": "content",
      "text": "1. Download the rghibernate JAR from the [download center](https://redis.com/redis-enterprise-software/download-center/modules/).\n\n1. Upload the JAR to a Redis node.\n\n1. Register rghibernate with RedisGears:\n\n    [code example]"
    },
    {
      "id": "configure-database-connection",
      "title": "Configure database connection",
      "role": "configuration",
      "text": "1. Create a [connector XML file](#connector-xml) with the configuration to connect Redis to an underlying database.\n\n1. Upload the file to a Redis node.\n\n1. Register the connector configuration:\n\n    [code example]"
    },
    {
      "id": "configure-data-mapping",
      "title": "Configure data mapping",
      "role": "configuration",
      "text": "1. Create a [mapping XML file](#mapping-xml) that defines how Redis maps data to an underlying database.\n\n1. Upload the file to a Redis node.\n\n1. Register the mapping configuration for write-behind:\n\n    [code example]`\n\n1. Register the same mapping configuration for read-through:\n\n    [code example]`"
    },
    {
      "id": "example-configuration",
      "title": "Example configuration",
      "role": "example",
      "text": "Here are some example configuration files for connecting to databases and mapping data."
    },
    {
      "id": "connector-xml",
      "title": "Connector XML",
      "role": "content",
      "text": "This configuration file contains connection details for an underlying MySQL database:\n\n[code example]"
    },
    {
      "id": "mapping-xml",
      "title": "Mapping XML",
      "role": "content",
      "text": "The following XML maps Redis hashes, which represent students, to a MySQL table:\n\n[code example]"
    },
    {
      "id": "commands",
      "title": "Commands",
      "role": "syntax",
      "text": "Run rghibernate commands with `RG.TRIGGER`:\n\n[code example]\n\nTo pass a file to a command like `SYNC.REGISTERCONNECTOR` or `SYNC.REGISTERSOURCE`, use the <nobr>`redis-cli -x`</nobr> option:\n\n[code example]"
    },
    {
      "id": "command-list",
      "title": "Command list",
      "role": "syntax",
      "text": "| Command | Description |\n|---------|-------------|\n| [SYNC.REGISTERCONNECTOR](#syncregisterconnector) | Register a new connector |\n| SYNC.UNREGISTERCONNECTOR | Unregister a connector (cannot have sources attached) |\n| [SYNC.REGISTERSOURCE](#syncregistersource) | Extra configuration based on policy |\n| SYNC.UNREGISTERSOURCE | Unregister a source |\n| SYNC.INFO SOURCES | Dump all sources |\n| SYNC.INFO CONNECTORS | Dump all connectors |"
    },
    {
      "id": "sync-registerconnector",
      "title": "SYNC.REGISTERCONNECTOR",
      "role": "content",
      "text": "[code example]\n\n| Name | Description |\n|------|-------------|\n| connector name | Name to give to your connector |\n| batch size | The size of the data sent to the backend in batches |\n| timeout | After this timeout, sends data to the backend even if the batch size was not reached |\n| retry interval | Retry interval on error |\n| connector xml | Hibernate XML definition of the connector |"
    },
    {
      "id": "sync-registersource",
      "title": "SYNC.REGISTERSOURCE",
      "role": "content",
      "text": "[code example]\n\n| Name | Description |\n|------|-------------|\n| source name | Name to give to your source |\n| connector name | Connector to send the data to |\n| policy | WriteBehind/WriteThrough/ReadThrough: <br></br>• On WriteThrough, an extra argument is WriteTimeout <br></br>• On ReadThrough, an extra argument is expire (0 for no expire) |\n| mapping xml | Hibernate XML definition of the mapping |"
    }
  ],
  "examples": [
    {
      "id": "register-rghibernate-jar-ex0",
      "language": "sh",
      "code": "$ redis-cli -x RG.JEXECUTE com.redislabs.WriteBehind < {filepath}/rghibernate-0.1.1-jar-with-dependencies.jar",
      "section_id": "register-rghibernate-jar"
    },
    {
      "id": "configure-database-connection-ex0",
      "language": "sh",
      "code": "> redis-cli -x RG.TRIGGER SYNC.REGISTERCONNECTOR mysql 1000 10 5 < src/test/resources/mysql_hibernate.cfg.xml \n    1) \"OK\"",
      "section_id": "configure-database-connection"
    },
    {
      "id": "configure-data-mapping-ex0",
      "language": "sh",
      "code": "> redis-cli -x RG.TRIGGER SYNC.REGISTERSOURCE StudentWrite mysql WriteBehind < src/test/resources/Student.hbm.xml \n    1) \"OK\"",
      "section_id": "configure-data-mapping"
    },
    {
      "id": "configure-data-mapping-ex1",
      "language": "sh",
      "code": "> redis-cli -x RG.TRIGGER SYNC.REGISTERSOURCE StudentRead mysql ReadThrough 0 < src/test/resources/Student.hbm.xml \n    1) \"OK\"",
      "section_id": "configure-data-mapping"
    },
    {
      "id": "connector-xml-ex0",
      "language": "xml",
      "code": "<!DOCTYPE hibernate-configuration PUBLIC\n        \"-//Hibernate/Hibernate Configuration DTD 3.0//EN\"\n  \"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd\">\n        \n<hibernate-configuration>\n  <session-factory>\n    <!-- JDBC Database connection settings -->\n    <property name=\"connection.driver_class\">org.mariadb.jdbc.Driver</property>\n    <property name=\"connection.url\">jdbc:mysql://localhost:3306/test?allowPublicKeyRetrieval=true&useSSL=false</property>\n    <property name=\"connection.username\">user</property>\n    <property name=\"connection.password\">pass</property>\n    <!-- JDBC connection pool settings ... using built-in test pool -->\n    <property name=\"connection.pool_size\">1</property>\n    <!-- Echo the SQL to stdout -->\n    <property name=\"show_sql\">false</property>\n    <!-- Set the current session context -->\n    <property name=\"current_session_context_class\">thread</property>\n    <!-- Drop and re-create the database schema on startup -->\n    <property name=\"hbm2ddl.auto\">update</property>\n    <!-- dbcp connection pool configuration -->\n    <property name=\"hibernate.dbcp.initialSize\">5</property>\n    <property name=\"hibernate.dbcp.maxTotal\">20</property>\n    <property name=\"hibernate.dbcp.maxIdle\">10</property>\n    <property name=\"hibernate.dbcp.minIdle\">5</property>\n    <property name=\"hibernate.dbcp.maxWaitMillis\">-1</property>\n  </session-factory>\n</hibernate-configuration>",
      "section_id": "connector-xml"
    },
    {
      "id": "mapping-xml-ex0",
      "language": "xml",
      "code": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<hibernate-mapping xmlns=\"http://www.hibernate.org/xsd/hibernate-mapping\"\n  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  xsi:schemaLocation=\"http://www.hibernate.org/xsd/hibernate-mapping\n    http://www.hibernate.org/xsd/hibernate-mapping/hibernate-mapping-4.0.xsd\">\n\n  <class entity-name=\"Student\" table=\"student\">\n          <tuplizer entity-mode=\"dynamic-map\" class=\"org.hibernate.tuple.entity.DynamicMapEntityTuplizer\"/>\n          <id name=\"id\" type=\"integer\" length=\"50\" column=\"id\"/>\n          <property name=\"firstName\" column=\"first_name\" type=\"string\"/>\n          <property name=\"lastName\" column=\"last_name\" type=\"string\"/>\n          <property name=\"email\" column=\"email\" type=\"string\" not-null=\"true\"/>\n          <property name=\"age\" column=\"age\" type=\"integer\"/>\n  </class>\n\n</hibernate-mapping>",
      "section_id": "mapping-xml"
    },
    {
      "id": "commands-ex0",
      "language": "sh",
      "code": "redis-cli RG.TRIGGER SYNC.<COMMAND>",
      "section_id": "commands"
    },
    {
      "id": "commands-ex1",
      "language": "sh",
      "code": "redis-cli -x RG.TRIGGER SYNC.{COMMAND} {arg1 arg2 ...} < {file}",
      "section_id": "commands"
    },
    {
      "id": "sync-registerconnector-ex0",
      "language": "sh",
      "code": "$ redis-cli -x RG.TRIGGER SYNC.REGISTERCONNECTOR \\\n    {connector name} {batch size} {timeout} {retry interval} \\\n    < {connector xml}",
      "section_id": "sync-registerconnector"
    },
    {
      "id": "sync-registersource-ex0",
      "language": "sh",
      "code": "redis-cli -x RG.TRIGGER SYNC.REGISTERSOURCE \\\n    {source name} {connector name} {policy} \\\n    < {mapping xml}",
      "section_id": "sync-registersource"
    }
  ]
}
