{"id":525,"date":"2018-09-15T15:00:06","date_gmt":"2018-09-15T06:00:06","guid":{"rendered":"https:\/\/weseek.co.jp\/tech\/?p=525"},"modified":"2023-04-17T11:57:31","modified_gmt":"2023-04-17T02:57:31","slug":"%e3%82%a2%e3%83%97%e3%83%aa%e3%82%b1%e3%83%bc%e3%82%b7%e3%83%a7%e3%83%b3%e9%96%8b%e7%99%ba%e3%81%ab%e3%81%8a%e3%81%91%e3%82%8b%e3%83%ad%e3%83%83%e3%82%af%e3%81%ae%e9%87%8d%e8%a6%81%e6%80%a7%e3%81%a8or","status":"publish","type":"post","link":"https:\/\/weseek.co.jp\/tech\/525\/","title":{"rendered":"\u958b\u767a\u3067\u306e\u30ed\u30c3\u30af\u306e\u91cd\u8981\u6027\u3068ORM\u306e\u30ed\u30c3\u30af\u5b9f\u73fe\u4f8b|\u697d\u89b3\u7684\u30ed\u30c3\u30af\u306e\u5229\u7528"},"content":{"rendered":"<p>\u524d\u56de\u8a18\u4e8b\u306e\u300c<a href=\"https:\/\/weseek.co.jp\/tech\/137\/\">\u958b\u767a\u3067\u306e\u30ed\u30c3\u30af\u306e\u91cd\u8981\u6027\u3068ORM\u3067\u306e\u30ed\u30c3\u30af\u306e\u5b9f\u73fe\u4f8b |\u697d\u89b3\u7684\u30ed\u30c3\u30af\u306e\u7d39\u4ecb<\/a>\u300d\u3067\u306f\u3001\u30c7\u30fc\u30bf\u306e\u4e0d\u6574\u5408\u304c\u767a\u751f\u3059\u308b\u72b6\u614b\u3068\u30c8\u30e9\u30f3\u30b6\u30af\u30b7\u30e7\u30f3\u306e\u5206\u96e2\u30ec\u30d9\u30eb\u306b\u3064\u3044\u3066\u8a73\u7d30\u3092\u7d39\u4ecb\u3057\u3001\u7d9a\u3044\u3066\u697d\u89b3\u7684\u30ed\u30c3\u30af\u3068\u60b2\u89b3\u7684\u30ed\u30c3\u30af\u306b\u3064\u3044\u3066\u7d39\u4ecb\u3057\u307e\u3057\u305f\u3002<\/p>\n<p>\u4eca\u56de\u306f<strong>\u697d\u89b3\u7684\u30ed\u30c3\u30af\u3092\u5229\u7528\u3059\u308b\u65b9\u6cd5<\/strong>\u306b\u3064\u3044\u3066<strong>\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af<\/strong>\u3084 <strong>O\/R \u30de\u30c3\u30d1\u30fc<\/strong>\u306e\u5177\u4f53\u4f8b\u3092\u7528\u3044\u3066\u7d39\u4ecb\u3057\u3066\u3044\u304d\u307e\u3059\u3002<\/p>\n<p><!--more--><\/p>\n\n<h2>\u697d\u89b3\u7684\u30ed\u30c3\u30af\u306e\u5b9f\u73fe\u4f8b<\/h2>\n<h3>Ruby on Rails \u306e\u5834\u5408<\/h3>\n<p>Ruby on Rails \u306e\u5834\u5408\u3001O\/R \u30de\u30c3\u30d1\u30fc\u3068\u3057\u3066 ActiveRecord \u304c\u4f7f\u308f\u308c\u3066\u3044\u307e\u3059\u3002<br \/>\n(<a href=\"https:\/\/en.wikipedia.org\/wiki\/Active_record_pattern\">ActiveRecord<\/a> \u3068\u306f O\/R \u30de\u30c3\u30d1\u30fc\u306e\u5b9f\u88c5\u30d1\u30bf\u30fc\u30f3\u306e\u540d\u524d\u3067\u3042\u308a\u3001\u540c\u3058\u540d\u524d\u304c\u4f7f\u308f\u308c\u3066\u3044\u307e\u3059\u3002)<\/p>\n<p>\u6b21\u306e\u30de\u30a4\u30b0\u30ec\u30fc\u30b7\u30e7\u30f3\u30d5\u30a1\u30a4\u30eb\u306e\u3088\u3046\u306b\u30e2\u30c7\u30eb\u306b <code>lock_version<\/code> \u30ab\u30e9\u30e0\u3092 integer \u578b\u3067\u4f5c\u6210\u3057\u307e\u3059\u3002<\/p>\n<pre><code># \u30de\u30a4\u30b0\u30ec\u30fc\u30b7\u30e7\u30f3\u30d5\u30a1\u30a4\u30eb\n$ cat db\/migrate\/20180906171026_create_users.rb\nclass CreateUsers < ActiveRecord::Migration[5.1]\n  def change\n    create_table :users do |t|\n\n      t.string :name, default: ''\n      t.timestamps\n      t.integer :lock_version\n    end\n  end\nend<\/code><\/pre>\n<p>\u3059\u308b\u3068\u3001ActiveRecord \u306f update \u30e1\u30bd\u30c3\u30c9\u3067\u30c7\u30fc\u30bf\u3092\u66f4\u65b0\u3059\u308b\u969b\u306b\u30ab\u30e9\u30e0\u306e lock_version \u3092\u30ab\u30a6\u30f3\u30c8\u30a2\u30c3\u30d7\u3057\u3066\u3001\u697d\u89b3\u7684\u30ed\u30c3\u30af\u3092\u5b9f\u73fe\u3057\u307e\u3059\u3002<\/p>\n<p>\u66f4\u65b0\u304c\u7af6\u5408\u3057\u305f\u5834\u5408\u306f\u3001 <code>ActiveRecord::StaleObjectError<\/code> \u304c\u767a\u751f\u3057\u307e\u3059\u3002<\/p>\n<pre><code># update\u5b9f\u884c\u6642\u306eSQL\u3067\u4f8b\u5916\u767a\u751f\u52d5\u4f5c\n## [\u30b9\u30ec\u30c3\u30c91] \u30e6\u30fc\u30b6(user1) \u3092\u4f5c\u6210\n[1] pry(main)> user1 = User.create!(name: 'test')\n   (0.0ms)  SAVEPOINT active_record_1\n  SQL (0.6ms)  INSERT INTO \"users\" (\"name\", \"created_at\", \"updated_at\", \"lock_version\") VALUES (?, ?, ?, ?)  [[\"name\", \"test\"], [\"created_at\", \"2018-09-06 17:23:40.408881\"], [\"updated_at\", \"2018-09-06 17:23:40.408881\"], [\"lock_version\", 0]]\n   (0.1ms)  RELEASE SAVEPOINT active_record_1\n=> #<User:0x00007fb2786676f0\n id: 1,\n name: \"test\",\n created_at: Thu, 06 Sep 2018 17:23:40 UTC +00:00,\n updated_at: Thu, 06 Sep 2018 17:23:40 UTC +00:00,\n lock_version: 0>\n\n## [\u30b9\u30ec\u30c3\u30c92] \u30e6\u30fc\u30b6(user1) \u3092\u53c2\u7167\n[2] pry(main)> user2 = User.find(1)\n  User Load (0.2ms)  SELECT  \"users\".* FROM \"users\" WHERE \"users\".\"id\" = ? LIMIT ?  [[\"id\", 1], [\"LIMIT\", 1]]\n=> #<User:0x00005605bcfecaf0\n id: 1,\n name: \"test\",\n created_at: Thu, 06 Sep 2018 17:23:40 UTC +00:00,\n updated_at: Thu, 06 Sep 2018 17:23:40 UTC +00:00,\n lock_version: 0>\n\n## [\u30b9\u30ec\u30c3\u30c91] \u30e6\u30fc\u30b6(user1) \u306e name \u3092 test2 \u306b\u66f4\u65b0\n[3] pry(main)> user1.update(name: 'test2')\n   (0.1ms)  SAVEPOINT active_record_1\n  SQL (0.2ms)  UPDATE \"users\" SET \"name\" = ?, \"updated_at\" = ?, \"lock_version\" = ? WHERE \"users\".\"id\" = ? AND \"users\".\"lock_version\" = ?  [[\"name\", \"test2\"], [\"updated_at\", \"2018-09-06 17:24:07.820275\"], [\"lock_version\", 1], [\"id\", 1], [\"lock_version\", 0]]\n   (0.1ms)  RELEASE SAVEPOINT active_record_1\n=> true\n\n## [\u30b9\u30ec\u30c3\u30c92] \u30e6\u30fc\u30b6(user1) \u306e namae \u3092 test3 \u306b\u66f4\u65b0(\u2605\u4f8b\u5916\u767a\u751f)\n[4] pry(main)> user2.update(name: 'test3')\n   (0.1ms)  SAVEPOINT active_record_1\n  SQL (0.2ms)  UPDATE \"users\" SET \"name\" = ?, \"updated_at\" = ?, \"lock_version\" = ? WHERE \"users\".\"id\" = ? AND \"users\".\"lock_version\" = ?  [[\"name\", \"test3\"], [\"updated_at\", \"2018-09-06 17:24:15.752651\"], [\"lock_version\", 1], [\"id\", 1], [\"lock_version\", 0]]\n   (0.1ms)  ROLLBACK TO SAVEPOINT active_record_1\nActiveRecord::StaleObjectError: Attempted to update a stale object: User.\nfrom \/usr\/local\/src\/rails-sample\/vendor\/bundle\/ruby\/2.5.0\/gems\/activerecord-5.1.6\/lib\/active_record\/locking\/optimistic.rb:95:in `_update_row'<\/code><\/pre>\n<h3>Grails \u306e\u5834\u5408<\/h3>\n<p>Grails \u3067\u306f O\/R \u30de\u30c3\u30d1\u30fc\u3068\u3057\u3066 GORM \u3092\u4f7f\u3044\u307e\u3059\u3002<br \/>\nGORM \u306f SQL DB \u3078\u30a2\u30af\u30bb\u30b9\u3059\u308b\u969b\u306b Hibernate \u3092\u5229\u7528\u3057\u307e\u3059\u3002<\/p>\n<p>\u30c7\u30d5\u30a9\u30eb\u30c8\u3067\u30c9\u30e1\u30a4\u30f3\u30af\u30e9\u30b9\u306b version \u30d7\u30ed\u30d1\u30c6\u30a3\u304c\u8ffd\u52a0\u3055\u308c\u3001\u697d\u89b3\u7684\u30ed\u30c3\u30af\u306e\u30d0\u30fc\u30b8\u30e7\u30f3\u3068\u3057\u3066\u5229\u7528\u3055\u308c\u307e\u3059\u3002<\/p>\n<pre><code># User\u30c9\u30e1\u30a4\u30f3\npackage grails.sample.app\n\nclass User {\n\n  String name\n\n  static constraints = {\n  }\n}<\/code><\/pre>\n<p>\u4e0a\u8a18\u306e\u3088\u3046\u306b\u3001version \u30d5\u30a3\u30fc\u30eb\u30c9\u3092\u30c9\u30e1\u30a4\u30f3\u30af\u30e9\u30b9\u306b\u660e\u793a\u7684\u306b\u6307\u5b9a\u3059\u308b\u5fc5\u8981\u306f\u3042\u308a\u307e\u305b\u3093\u3002\u30c7\u30d5\u30a9\u30eb\u30c8\u3067\u8ffd\u52a0\u3055\u308c\u307e\u3059\u3002(\u9006\u306b\u697d\u89b3\u7684\u30ed\u30c3\u30af\u3092\u4f7f\u3044\u305f\u304f\u306a\u3044\u5834\u5408\u306f <code>version false<\/code> \u3092 mapping \u306b\u6307\u5b9a\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059)<\/p>\n<pre><code>\/\/ User\u30c9\u30e1\u30a4\u30f3\u306e name \u3092 test2 \u306b\u5909\u66f4\ndef user = User.get(1)\nprintln 'name: ' + user.name + ', version: ' + user.version\nuser.name = 'test2'\nuser.save(flush: true)\nprintln 'name: ' + user.name + ', version: ' + user.version\n\n\/\/ \u5b9f\u884c\u7d50\u679c\nname: test, version: 40\nname: test2, version: 41<\/code><\/pre>\n<p>\u4f8b\u5916\u304c\u767a\u751f\u3059\u308b\u3068 <code>org.springframework.dao.OptimisticLockingFailureException<\/code> \u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3059\u3002<\/p>\n<h3>SQLAlchemy \u306e\u5834\u5408<\/h3>\n<p>SQLAlchemy \u306f O\/R \u30de\u30c3\u30d1\u30fc\u3092\u542b\u3080 Python \u7528\u306e SQL Toolkit \u3067\u3059\u3002<\/p>\n<p>\u6b21\u306e\u30d5\u30a1\u30a4\u30eb\u306e\u3088\u3046\u306b\u30e2\u30c7\u30eb\u306b\u6570\u5024\u3092\u4fdd\u5b58\u3059\u308b\u4efb\u610f\u306e\u30d5\u30a3\u30fc\u30eb\u30c9(BigInteger \u578b\u7b49) \u3067\u4f5c\u6210\u3057\u3001 <code>__mapper_args__<\/code> \u306e\u5b9a\u7fa9\u5185\u3067 <code>version_id_col<\/code> \u3068\u3057\u3066\u8a2d\u5b9a\u3057\u307e\u3059\u3002<\/p>\n<pre><code>from sqlalchemy import *\nfrom sqlalchemy.orm import *\nfrom sqlalchemy.ext.declarative import declarative_base\nfrom sqlalchemy import Column, Integer, String\n\nclass User(Base):\n  __tablename__ = 'users'\n\n  id = Column('id', Integer, primary_key = True)\n  name = Column('name', String(200))\n  version_id = Column(BigInteger, nullable=False)\n\n  __mapper_args__ = {\n    'version_id_col': version_id\n  }<\/code><\/pre>\n<p>\u3059\u308b\u3068\u3001SQLAlchemy \u306f\u30bb\u30c3\u30b7\u30e7\u30f3\u304c commit \u3055\u308c\u3066\u30c7\u30fc\u30bf\u3092\u66f4\u65b0\u3059\u308b\u969b\u306b\u30ab\u30e9\u30e0\u306e version_id \u3092\u30ab\u30a6\u30f3\u30c8\u30a2\u30c3\u30d7\u3057\u3066\u3001\u697d\u89b3\u7684\u30ed\u30c3\u30af\u3092\u5b9f\u73fe\u3057\u307e\u3059\u3002<\/p>\n<p>\u66f4\u65b0\u304c\u7af6\u5408\u3057\u305f\u5834\u5408\u306f\u3001 <code>sqlalchemy.orm.exc.StaleDataError<\/code> \u304c\u767a\u751f\u3057\u307e\u3059\u3002<\/p>\n<pre><code># \u30b9\u30ec\u30c3\u30c91\n## \u30e2\u30c7\u30eb\u30d5\u30a1\u30a4\u30eb\u3068 DB Connector \u306e\u8aad\u307f\u8fbc\u307f\n>&gt;&gt; from setting import session\n>&gt;&gt; from user import *\n\n## User \u306e name \u3092 test \u3068\u3057\u3066\u4f5c\u6210\n>&gt;&gt; user = User()\n>&gt;&gt; user.name = &#039;test&#039;\n>&gt;&gt; session.add(user)\n>&gt;&gt; session.commit()\n\n## User \u306e name \u3092 test6 \u3078\u5909\u66f4\n>&gt;&gt; user.name = &#039;test6&#039;\n>&gt;&gt; session.commit()\n2018-09-11 03:34:45,280 INFO sqlalchemy.engine.base.Engine UPDATE users SET name=%s, version_id=%s WHERE users.id = %s AND users.version_id = %s\n2018-09-11 03:34:45,280 INFO sqlalchemy.engine.base.Engine (&#039;test6&#039;, 4, 1, 3)\n2018-09-11 03:34:45,281 INFO sqlalchemy.engine.base.Engine COMMIT\n>&gt;&gt; \n\n# \u30b9\u30ec\u30c3\u30c92\n## \u30e2\u30c7\u30eb\u30d5\u30a1\u30a4\u30eb\u3068 DB Connector \u306e\u8aad\u307f\u8fbc\u307f\n>&gt;&gt; from setting import session\n>&gt;&gt; from user import *\n\n## User \u3092\u53d6\u5f97\n>&gt;&gt; user = session.query(User).filter(User.id==1).first()\n2018-09-11 03:33:34,195 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES LIKE &#039;sql_mode&#039;\n2018-09-11 03:33:34,196 INFO sqlalchemy.engine.base.Engine ()\n2018-09-11 03:33:34,198 INFO sqlalchemy.engine.base.Engine SELECT DATABASE()\n2018-09-11 03:33:34,198 INFO sqlalchemy.engine.base.Engine ()\n2018-09-11 03:33:34,198 INFO sqlalchemy.engine.base.Engine show collation where `Charset` = &#039;utf8mb4&#039; and `Collation` = &#039;utf8mb4_bin&#039;\n2018-09-11 03:33:34,198 INFO sqlalchemy.engine.base.Engine ()\n2018-09-11 03:33:34,200 INFO sqlalchemy.engine.base.Engine SELECT CAST(&#039;test plain returns&#039; AS CHAR(60)) AS anon_1\n2018-09-11 03:33:34,200 INFO sqlalchemy.engine.base.Engine ()\n2018-09-11 03:33:34,201 INFO sqlalchemy.engine.base.Engine SELECT CAST(&#039;test unicode returns&#039; AS CHAR(60)) AS anon_1\n2018-09-11 03:33:34,201 INFO sqlalchemy.engine.base.Engine ()\n2018-09-11 03:33:34,202 INFO sqlalchemy.engine.base.Engine SELECT CAST(&#039;test collated returns&#039; AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_bin AS anon_1\n2018-09-11 03:33:34,202 INFO sqlalchemy.engine.base.Engine ()\n2018-09-11 03:33:34,202 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)\n2018-09-11 03:33:34,203 INFO sqlalchemy.engine.base.Engine SELECT users.id AS users_id, users.name AS users_name, users.version_id AS users_version_id \nFROM users \nWHERE users.id = %s \n LIMIT %s\n2018-09-11 03:33:34,203 INFO sqlalchemy.engine.base.Engine (1, 1)\n\n## User \u306e name \u3092 test5 \u306b\u5909\u66f4\u3059\u308b(\u2605\u4f8b\u5916\u767a\u751f)\n>&gt;&gt; user.name = &#039;test5&#039;\n>&gt;&gt; session.add(user)\n>&gt;&gt; session.commit()\n2018-09-11 03:35:00,504 INFO sqlalchemy.engine.base.Engine UPDATE users SET name=%s, version_id=%s WHERE users.id = %s AND users.version_id = %s\n2018-09-11 03:35:00,504 INFO sqlalchemy.engine.base.Engine (&#039;test5&#039;, 4, 1, 3)\n2018-09-11 03:35:00,504 INFO sqlalchemy.engine.base.Engine ROLLBACK\nTraceback (most recent call last):\n  File &quot;&lt;console&gt;&quot;, line 1, in &lt;module&gt;\n  File &quot;\/PATH\/lib\/python3.5\/site-packages\/sqlalchemy\/orm\/session.py&quot;, line 943, in commit\n    self.transaction.commit()\n  File &quot;\/PATH\/lib\/python3.5\/site-packages\/sqlalchemy\/orm\/session.py&quot;, line 467, in commit\n    self._prepare_impl()\n  File &quot;\/PATH\/lib\/python3.5\/site-packages\/sqlalchemy\/orm\/session.py&quot;, line 447, in _prepare_impl\n    self.session.flush()\n  File &quot;\/PATH\/lib\/python3.5\/site-packages\/sqlalchemy\/orm\/session.py&quot;, line 2254, in flush\n    self._flush(objects)\n  File &quot;\/PATH\/lib\/python3.5\/site-packages\/sqlalchemy\/orm\/session.py&quot;, line 2380, in _flush\n    transaction.rollback(_capture_exception=True)\n  File &quot;\/PATH\/lib\/python3.5\/site-packages\/sqlalchemy\/util\/langhelpers.py&quot;, line 66, in __exit__\n    compat.reraise(exc_type, exc_value, exc_tb)\n  File &quot;\/PATH\/lib\/python3.5\/site-packages\/sqlalchemy\/util\/compat.py&quot;, line 249, in reraise\n    raise value\n  File &quot;\/PATH\/lib\/python3.5\/site-packages\/sqlalchemy\/orm\/session.py&quot;, line 2344, in _flush\n    flush_context.execute()\n  File &quot;\/PATH\/lib\/python3.5\/site-packages\/sqlalchemy\/orm\/unitofwork.py&quot;, line 391, in execute\n    rec.execute(self)\n  File &quot;\/PATH\/lib\/python3.5\/site-packages\/sqlalchemy\/orm\/unitofwork.py&quot;, line 556, in execute\n    uow\n  File &quot;\/PATH\/lib\/python3.5\/site-packages\/sqlalchemy\/orm\/persistence.py&quot;, line 177, in save_obj\n    mapper, table, update)\n  File &quot;\/PATH\/lib\/python3.5\/site-packages\/sqlalchemy\/orm\/persistence.py&quot;, line 791, in _emit_update_statements\n    (table.description, len(records), rows))\nsqlalchemy.orm.exc.StaleDataError: UPDATE statement on table &#039;users&#039; expected to update 1 row(s); 0 were matched.<\/code><\/pre>\n<h3>O\/R \u30de\u30c3\u30d1\u30fc\u306b\u304a\u3051\u308b\u697d\u89b3\u7684\u30ed\u30c3\u30af\u306e\u5b9f\u88c5\u6709\u7121<\/h3>\n<p>\u3053\u3053\u307e\u3067\u3067\u3001\u5e7e\u3064\u304b\u306e O\/R \u30de\u30c3\u30d1\u30fc\u3092\u4f7f\u3063\u3066\u697d\u89b3\u7684\u30ed\u30c3\u30af\u3092\u5b9f\u88c5\u3059\u308b\u305f\u3081\u306e\u5177\u4f53\u4f8b\u3092\u898b\u3066\u304d\u307e\u3057\u305f\u3002<\/p>\n<p>\u4ed6\u306e O\/R \u30de\u30c3\u30d1\u30fc\u3092\u542b\u3081\u3066\u3001\u697d\u89b3\u7684\u30ed\u30c3\u30af\u306e\u5b9f\u88c5\u304c\u3042\u308b\u304b\u3069\u3046\u304b\u4ee5\u4e0b\u306b\u7e8f\u3081\u307e\u3059\u3002<\/p>\n<table>\n<thead>\n<tr>\n<th>ORM\u540d<\/th>\n<th>\u697d\u89b3\u7684\u30ed\u30c3\u30af\u306e\u5b9f\u88c5\u6709\u7121<\/th>\n<th>\u767a\u751f\u3059\u308b\u4f8b\u5916<\/th>\n<th>\u53c2\u8003\u60c5\u5831<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>GORM<\/td>\n<td>\u3007<\/td>\n<td>org.springframework.dao.OptimisticLockingFailureException<\/td>\n<td><a href=\"http:\/\/gorm.grails.org\/latest\/hibernate\/manual\/index.html#locking\">GORM for Hibernate &gt; Pessimistic and Optimistic Locking<\/a><\/td>\n<\/tr>\n<tr>\n<td>ActiveRecord<\/td>\n<td>\u3007<\/td>\n<td>ActiveRecord::StaleObjectError<\/td>\n<td><a href=\"https:\/\/api.rubyonrails.org\/classes\/ActiveRecord\/Locking\/Optimistic.html\">Ruby on Rails API &gt; ActiveRecord::Locking::Optimistic<\/a><\/td>\n<\/tr>\n<tr>\n<td>SQLAlchemy<\/td>\n<td>\u3007<\/td>\n<td>sqlalchemy.orm.exc.StaleDataError<\/td>\n<td><a href=\"https:\/\/docs.sqlalchemy.org\/en\/latest\/orm\/mapping_api.html?highlight=version_id#sqlalchemy.orm.mapper.params.version_id_col\">SQLAlchemy &gt; Class Mapping API<\/a><\/td>\n<\/tr>\n<tr>\n<td>Hibernate<\/td>\n<td>\u3007<\/td>\n<td>org.hibernate.StaleObjectStateException<\/td>\n<td><a href=\"http:\/\/www.masatom.in\/pukiwiki\/Hibernate\/%B3%DA%B4%D1%C5%AA%A5%ED%A5%C3%A5%AF%A4%F2%BC%C2%C1%F5%A4%B9%A4%EB\/\">Hibernate\/\u697d\u89b3\u7684\u30ed\u30c3\u30af\u3092\u5b9f\u88c5\u3059\u308b<\/a><\/td>\n<\/tr>\n<tr>\n<td>JPA<\/td>\n<td>\u3007<\/td>\n<td>javax.persistence.OptimisticLockException<\/td>\n<td><a href=\"https:\/\/docs.oracle.com\/javaee\/7\/api\/javax\/persistence\/OptimisticLockException.html\">Java7 API - Class OptimisticLockException<\/a><\/td>\n<\/tr>\n<tr>\n<td>Eclipse Link\uff08Toplink Essentials\uff09<\/td>\n<td>\u3007<\/td>\n<td>javax.persistence.OptimisticLockException<\/td>\n<td>\u203bEclipse Link \u306f JPA \u306e\u5b9f\u88c5\u3067\u3042\u308b\u3002<a href=\"https:\/\/stackoverflow.com\/questions\/553263\/what-is-the-difference-between-toplink-essentials-eclipselink\">stack overflow - what-is-the-difference-between-toplink-essentials-eclipselink<\/a><\/td>\n<\/tr>\n<tr>\n<td>MyBATIS(\u65e7iBATIS)<\/td>\n<td>\u00d7<\/td>\n<td>-<\/td>\n<td><a href=\"https:\/\/www.nakamuri.info\/mw\/index.php\/MyBatis%E3%81%A7%E8%A1%8C%E3%83%AD%E3%83%83%E3%82%AF%28%E6%82%B2%E8%A6%B3%E3%83%AD%E3%83%83%E3%82%AF%29%E3%82%92%E8%A1%8C%E3%81%86%E3%81%AB%E3%81%AF%EF%BC%9F\">MyBatis\u3067\u884c\u30ed\u30c3\u30af(\u60b2\u89b3\u30ed\u30c3\u30af)\u3092\u884c\u3046\u306b\u306f\uff1f<\/a><\/td>\n<\/tr>\n<tr>\n<td>Django \u306e ORM<\/td>\n<td>\u00d7<\/td>\n<td>-<\/td>\n<\/tr>\n<tr>\n<td>Sequelize<\/td>\n<td>\u3007<\/td>\n<td>OptimisticLockError<\/td>\n<td><a href=\"http:\/\/docs.sequelizejs.com\/manual\/tutorial\/models-definition.html#optimistic-locking\">Sequelize &gt; Model definition &gt; Optimistic Locking<\/a><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>NoSQL \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b\u304a\u3051\u308b\u697d\u89b3\u7684\u30ed\u30c3\u30af\u5b9f\u88c5\u306b\u3064\u3044\u3066<\/h2>\n<p>\u30c8\u30e9\u30f3\u30b6\u30af\u30b7\u30e7\u30f3\u51e6\u7406\u304c\u5b58\u5728\u3057\u306a\u3044 NoSQL \u3067\u306f\u697d\u89b3\u7684\u30ed\u30c3\u30af\u304c\u591a\u304f\u4f7f\u308f\u308c\u3066\u3044\u308b\u3002<br \/>\n(Memcached \u306e CAS(Check and Set) \u304c\u697d\u89b3\u7684\u30ed\u30c3\u30af\u3092\u6307\u3059)<br \/>\n\u203b\u53c2\u8003: <a href=\"https:\/\/www.slideshare.net\/crumbjp\/db-tech-showcase-mongodb\">Slide Share - db-tech-showcase-mongodb<\/a>P.44-50 \u4ed8\u8fd1<\/p>\n<h3>O\/R \u30de\u30c3\u30d1\u30fc\u306b\u304a\u3051\u308b\u697d\u89b3\u7684\u30ed\u30c3\u30af\u306e\u5b9f\u88c5\u6709\u7121<\/h3>\n<table>\n<thead>\n<tr>\n<th>ORM\u540d<\/th>\n<th>\u697d\u89b3\u7684\u30ed\u30c3\u30af\u306e\u5b9f\u88c5\u6709\u7121<\/th>\n<th>\u767a\u751f\u3059\u308b\u4f8b\u5916<\/th>\n<th>\u53c2\u8003\u60c5\u5831<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Mongoose<\/td>\n<td>\u3007<\/td>\n<td>VersionError<\/td>\n<td><a href=\"https:\/\/mongoosejs.com\/docs\/guide.html#versionKey\">mongoose &gt; versionKey<\/a><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>\u6700\u5f8c\u306b<\/h2>\n<p>\u4eca\u56de\u306f\u3044\u304f\u3064\u304b\u5177\u4f53\u7684\u306a OR \u30de\u30c3\u30d1\u30fc\u3092\u4f8b\u306b\u3057\u3066\u697d\u89b3\u7684\u30ed\u30c3\u30af\u3092\u5229\u7528\u3059\u308b\u65b9\u6cd5\u3092\u7d39\u4ecb\u3057\u3001OR \u30de\u30c3\u30d1\u30fc\u306b\u304a\u3044\u3066\u697d\u89b3\u7684\u30ed\u30c3\u30af\u3092\u5b9f\u88c5\u3057\u3066\u3044\u308b\u304b\u3069\u3046\u304b\u3092\u307e\u3068\u3081\u3066\u7d39\u4ecb\u3057\u307e\u3057\u305f\u3002<\/p>\n<p>3\u56de\u306b\u6e21\u3063\u3066\u7d39\u4ecb\u3057\u3066\u304d\u305f\u697d\u89b3\u7684\u30ed\u30c3\u30af\u306b\u95a2\u9023\u3059\u308b\u8a18\u4e8b\u306f\u4eca\u56de\u3067\u6700\u7d42\u56de\u3068\u306a\u308a\u307e\u3059\u3002<\/p>\n<p>\u30bd\u30d5\u30c8\u30a6\u30a7\u30a2\u3092\u6271\u3046\u4e0a\u3067\u91cd\u8981\u306a\u30ed\u30c3\u30af\u306b\u3064\u3044\u3066\u3001\u7686\u3055\u3093\u304c\u7406\u89e3\u3059\u308b\u30fb\u5fa9\u7fd2\u3059\u308b\u305f\u3081\u306e\u4e00\u52a9\u3068\u306a\u308a\u307e\u3057\u305f\u3089\u5e78\u3044\u3067\u3059\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u524d\u56de\u8a18\u4e8b\u306e\u300c\u958b\u767a\u3067\u306e\u30ed\u30c3\u30af\u306e\u91cd\u8981\u6027\u3068ORM\u3067\u306e\u30ed\u30c3\u30af\u306e\u5b9f\u73fe\u4f8b |\u697d\u89b3\u7684\u30ed\u30c3\u30af\u306e\u7d39\u4ecb\u300d\u3067\u306f\u3001\u30c7\u30fc\u30bf\u306e\u4e0d\u6574\u5408\u304c\u767a\u751f\u3059\u308b\u72b6\u614b\u3068\u30c8\u30e9\u30f3\u30b6\u30af\u30b7\u30e7\u30f3\u306e\u5206\u96e2\u30ec\u30d9\u30eb\u306b\u3064\u3044\u3066\u8a73\u7d30\u3092\u7d39\u4ecb\u3057\u3001\u7d9a\u3044\u3066\u697d\u89b3\u7684\u30ed\u30c3\u30af\u3068\u60b2\u89b3\u7684\u30ed\u30c3\u30af\u306b\u3064\u3044\u3066\u7d39\u4ecb\u3057\u307e\u3057<\/p>\n","protected":false},"author":3,"featured_media":527,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[192],"tags":[],"_links":{"self":[{"href":"https:\/\/weseek.co.jp\/tech\/wp-json\/wp\/v2\/posts\/525"}],"collection":[{"href":"https:\/\/weseek.co.jp\/tech\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/weseek.co.jp\/tech\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/weseek.co.jp\/tech\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/weseek.co.jp\/tech\/wp-json\/wp\/v2\/comments?post=525"}],"version-history":[{"count":13,"href":"https:\/\/weseek.co.jp\/tech\/wp-json\/wp\/v2\/posts\/525\/revisions"}],"predecessor-version":[{"id":4107,"href":"https:\/\/weseek.co.jp\/tech\/wp-json\/wp\/v2\/posts\/525\/revisions\/4107"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/weseek.co.jp\/tech\/wp-json\/wp\/v2\/media\/527"}],"wp:attachment":[{"href":"https:\/\/weseek.co.jp\/tech\/wp-json\/wp\/v2\/media?parent=525"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/weseek.co.jp\/tech\/wp-json\/wp\/v2\/categories?post=525"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/weseek.co.jp\/tech\/wp-json\/wp\/v2\/tags?post=525"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}