{"id":158547,"date":"2012-11-13T23:30:03","date_gmt":"2012-11-13T19:30:03","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=158547"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=158547","title":{"rendered":"<span class=\"post_title\">\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 CompositeUserType \u0434\u043b\u044f \u0441\u0432\u044f\u0437\u0438 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 \u0432 Hibernate<\/span>"},"content":{"rendered":"<div class=\"content html_format\">   \t<i>\u041f\u043e\u0441\u0442 \u0431\u0443\u0434\u0435\u0442 \u043a\u0440\u0430\u0442\u043a\u0438\u043c \u0438 \u0432\u0435\u0441\u044c\u043c\u0430 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u043c.<\/i><\/p>\n<h5>\u0417\u0430\u0434\u0430\u0447\u0430<\/h5>\n<p>  \u0415\u0441\u0442\u044c Java-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0438\u043c\u0435\u044e\u0449\u0435\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e ORM-\u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 (Entity).<br \/>  \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c ExtendedAttributes, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u0438\u0442\u044c \u043a \u043b\u044e\u0431\u043e\u0439 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 <b>\u0431\u0435\u0437 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u043a\u0438<\/b>.<\/p>\n<h5>\u0420\u0435\u0448\u0435\u043d\u0438\u0435<\/h5>\n<p>  \u041d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u043a \u043d\u0430\u043c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 CompositeUserType, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0435\u0431\u044f class \u0438 id \u0442\u043e\u0439 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u0442\u044c. \u0412\u043e\u0442 \u0438 \u0432\u0441\u0451 \u0440\u0435\u0448\u0435\u043d\u0438\u0435. \u0410 \u0434\u0430\u043b\u044c\u0448\u0435 \u2014 \u043a\u043e\u0434.<br \/>  <a name=\"habracut\"><\/a><br \/>  \u0414\u043b\u044f \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u0442\u0430 \u0438\u043c\u043f\u043e\u0440\u0442\u044b, \u0433\u0435\u0442\u0442\u0435\u0440\u044b, \u0441\u0435\u0442\u0442\u0435\u0440\u044b \u0438 \u043c\u0435\u0442\u043e\u0434\u044b \u00ab\u043f\u043e-\u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e\u00bb \u0438\u0437 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0432\u044b\u0440\u0435\u0437\u0430\u043d\u044b.<\/p>\n<p>  <b>ExtendedAttributes.class<\/b> \u2014 \u0438\u043c\u0435\u043d\u043d\u043e \u0435\u0433\u043e \u043c\u044b \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0434\u0430\u043d\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438  <\/p>\n<pre><code class=\"java\">@Entity @Table(name = &quot;extattributes&quot;) @TypeDef(name = &quot;entityType&quot;, typeClass = hibernate.GenericEntityType.class) public class ExtendedAttributes extends GenericEntity { \tprivate static final long serialVersionUID = 1L; \t@Id \tprivate Long id; \t@Type(type = &quot;entityType&quot;) \t@Columns(columns = { @Column(name = &quot;object_id&quot;), \t\t\t@Column(name = &quot;object_class&quot;) }) \tprivate GenericEntity object; \tprivate String property; \tprivate String value;  \t@Override \tpublic Class&lt;?&gt; getType() { \t\treturn ExtendedAttributes.class; \t}         @Override \tpublic Long getId() { \t\treturn id; \t}  } <\/code><\/pre>\n<p>  <b>GenericEntity.class<\/b> \u2014 \u0435\u0433\u043e \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u044e\u0442 \u0432\u0441\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438.  <\/p>\n<pre><code class=\"java\">public abstract class GenericEntity implements Serializable { \tprivate static final long serialVersionUID = 1L; \tpublic abstract Serializable getId(); \tpublic abstract Class&lt;?&gt; getType(); } <\/code><\/pre>\n<p>  <b>EntityWrapper.class<\/b> \u2014 \u043e\u0431\u0435\u0440\u0442\u043a\u0430 \u0434\u043b\u044f \u043d\u0435\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439.  <\/p>\n<pre><code class=\"java\">public class EntityWrapper extends GenericEntity { \tprivate static final long serialVersionUID = 1L; \tprivate String name;  \tpublic EntityWrapper(String name) { \t\tsuper(); \t\tthis.name = name; \t}  \t@Override \tpublic Serializable getId() { \t\treturn name; \t}  \t@Override \tpublic Class&lt;?&gt; getType() { \t\treturn EntityWrapper.class; \t}  } <\/code><\/pre>\n<p>  <b>GenericEntityType.class<\/b> \u2014 \u0430 \u0432\u043e\u0442 \u0438 \u0442\u043e\u0442 \u0441\u0430\u043c\u044b\u0439 \u0442\u0438\u043f. \u0421\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0434\u0432\u0443\u0445 String-\u043f\u043e\u043b\u0435\u0439, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 GenericEntity.<br \/>  <b>determineIdType()<\/b> \u2014 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u043a\u043e\u0441\u0442\u044b\u043b\u044c, \u043d\u043e \u0447\u0435\u043c \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u044f \u043f\u043e\u043a\u0430 \u043d\u0435 \u043d\u0430\u0448\u0435\u043b.<br \/>  Id \u0434\u0440\u0443\u0433\u0438\u0445 \u0442\u0438\u043f\u043e\u0432 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u043d\u0435\u0442.<\/p>\n<pre><code class=\"java\">public class GenericEntityType implements CompositeUserType { \tprivate static final Type[] SQL_TYPES = { StringType.INSTANCE, \t\t\tStringType.INSTANCE }; \tprivate static final String[] SQL_NAMES = { &quot;id&quot;, &quot;class&quot; };  \t@Override \tpublic String[] getPropertyNames() { \t\treturn SQL_NAMES; \t}  \t@Override \tpublic Type[] getPropertyTypes() { \t\treturn SQL_TYPES; \t}  \t@Override \tpublic Class&lt;?&gt; returnedClass() { \t\treturn GenericEntity.class; \t}  \t@Override \tpublic boolean equals(Object o1, Object o2) throws HibernateException { \t\tif (o1 == o2) \t\t\treturn true; \t\tif (o1 != null && o2 != null) \t\t\treturn o1.equals(o2); \t\treturn false; \t}  \t@Override \tpublic Object getPropertyValue(Object object, int index) \t\t\tthrows HibernateException { \t\tGenericEntity dto = (GenericEntity) object; \t\tif (index == 0) { \t\t\treturn dto.getId(); \t\t} else if (index == 1) { \t\t\treturn dto.getType(); \t\t} else { \t\t\tthrow new HibernateException(&quot;Unknown index [ &quot; + index + &quot; ]&quot;); \t\t} \t}  \t@Override \tpublic int hashCode(Object object) throws HibernateException { \t\treturn (object != null) ? object.hashCode() : 0; \t}  \t@Override \tpublic boolean isMutable() { \t\treturn false; \t}  \t@Override \tpublic Object nullSafeGet(ResultSet rs, String[] names, \t\t\tSessionImplementor session, Object owner) \t\t\tthrows HibernateException, SQLException { \t\tif (names.length == 2) { \t\t\tString id = (String) StringType.INSTANCE.get(rs, names[0], session); \t\t\tString clazz = (String) StringType.INSTANCE.get(rs, names[1], \t\t\t\t\tsession); \t\t\tif (id != null && clazz != null) { \t\t\t\ttry { \t\t\t\t\tClass.forName(clazz); \t\t\t\t\treturn session.immediateLoad(clazz, determineIdType(id)); \t\t\t\t} catch (ClassNotFoundException e) { \t\t\t\t\treturn new EntityWrapper(id); \t\t\t\t} \t\t\t} \t\t} \t\treturn null; \t}  \t@Override \tpublic void nullSafeSet(PreparedStatement st, Object value, int index, \t\t\tSessionImplementor session) throws HibernateException, SQLException { \t\tif (value == null) { \t\t\tStringType.INSTANCE.set(st, null, index, session); \t\t\tClassType.INSTANCE.set(st, null, index + 1, session); \t\t} else { \t\t\tfinal GenericEntity dto = (GenericEntity) value; \t\t\tStringType.INSTANCE.set(st, dto.getId().toString(), index, session); \t\t\tClassType.INSTANCE.set(st, dto.getType(), index + 1, session); \t\t}  \t}  \t\/** \t * \u0410\u0432\u0442\u043e\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0442\u0438\u043f\u0430. Long\/String\/Double \t *  \t * @param id \t * @return \t *\/ \tprivate Serializable determineIdType(String id) { \t\ttry { \t\t\tif (id.matches(&quot;^\\\\d+$&quot;)) { \t\t\t\treturn Long.valueOf(id); \t\t\t} else if (id.matches(&quot;^\\\\d+[\\\\.,]\\\\d+$&quot;)) { \t\t\t\treturn Double.valueOf(id); \t\t\t} else { \t\t\t\treturn id; \t\t\t} \t\t} catch (NumberFormatException e) { \t\t\treturn id; \t\t} \t} <\/code><\/pre>\n<p>  \u0410 \u0442\u0435\u043f\u0435\u0440\u044c \u2014 \u043a\u0430\u043a \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c:  <\/p>\n<pre><code class=\"java\">\tpublic static Criterion criterionForEntity(String field, GenericEntity object) { \t\tString id = &quot;&quot;; \t\tif (object.getId() != null) { \t\t\tid = object.getId().toString(); \t\t} \t\treturn Restrictions.and(Restrictions.eq(field + &quot;.id&quot;, id), \t\t\t\tRestrictions.eq(field + &quot;.class&quot;, object.getType() \t\t\t\t\t\t.getCanonicalName())); \t} <\/code><\/pre>\n<p>  \u0421\u043f\u0430\u0441\u0438\u0431\u043e \u0437\u0430 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435. \u041d\u0430\u0434\u0435\u044e\u0441\u044c, \u044d\u0442\u043e \u0432\u0430\u043c \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f \ud83d\ude42    \t   \t<\/p>\n<div class=\"clear\"><\/div>\n<\/p><\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"http:\/\/habrahabr.ru\/post\/158547\/\"> http:\/\/habrahabr.ru\/post\/158547\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"content html_format\">   \t<i>\u041f\u043e\u0441\u0442 \u0431\u0443\u0434\u0435\u0442 \u043a\u0440\u0430\u0442\u043a\u0438\u043c \u0438 \u0432\u0435\u0441\u044c\u043c\u0430 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u043c.<\/i><\/p>\n<h5>\u0417\u0430\u0434\u0430\u0447\u0430<\/h5>\n<p>  \u0415\u0441\u0442\u044c Java-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0438\u043c\u0435\u044e\u0449\u0435\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e ORM-\u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 (Entity).<br \/>  \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c ExtendedAttributes, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u0438\u0442\u044c \u043a \u043b\u044e\u0431\u043e\u0439 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 <b>\u0431\u0435\u0437 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u043a\u0438<\/b>.<\/p>\n<h5>\u0420\u0435\u0448\u0435\u043d\u0438\u0435<\/h5>\n<p>  \u041d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u043a \u043d\u0430\u043c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 CompositeUserType, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0435\u0431\u044f class \u0438 id \u0442\u043e\u0439 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u0442\u044c. \u0412\u043e\u0442 \u0438 \u0432\u0441\u0451 \u0440\u0435\u0448\u0435\u043d\u0438\u0435. \u0410 \u0434\u0430\u043b\u044c\u0448\u0435 \u2014 \u043a\u043e\u0434.  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-158547","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/158547","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=158547"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/158547\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=158547"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=158547"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=158547"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}