|
24 | 24 | import org.hibernate.internal.CoreLogging;
|
25 | 25 | import org.hibernate.internal.CoreMessageLogger;
|
26 | 26 | import org.hibernate.persister.entity.EntityPersister;
|
27 |
| -import org.hibernate.pretty.MessageHelper; |
28 | 27 | import org.hibernate.type.BasicType;
|
29 | 28 | import org.hibernate.type.Type;
|
30 | 29 |
|
| 30 | +import static org.hibernate.pretty.MessageHelper.infoString; |
| 31 | + |
31 | 32 | /**
|
32 | 33 | * Defines the default replicate event listener used by Hibernate to replicate
|
33 | 34 | * entities in response to generated replicate events.
|
@@ -55,79 +56,72 @@ public void onReplicate(ReplicateEvent event) {
|
55 | 56 | final PersistenceContext persistenceContext = source.getPersistenceContextInternal();
|
56 | 57 | if ( persistenceContext.reassociateIfUninitializedProxy( event.getObject() ) ) {
|
57 | 58 | LOG.trace( "Uninitialized proxy passed to replicate()" );
|
58 |
| - return; |
59 | 59 | }
|
60 |
| - |
61 |
| - Object entity = persistenceContext.unproxyAndReassociate( event.getObject() ); |
62 |
| - |
63 |
| - if ( persistenceContext.isEntryFor( entity ) ) { |
64 |
| - LOG.trace( "Ignoring persistent instance passed to replicate()" ); |
65 |
| - //hum ... should we cascade anyway? throw an exception? fine like it is? |
66 |
| - return; |
| 60 | + else { |
| 61 | + final Object entity = persistenceContext.unproxyAndReassociate( event.getObject() ); |
| 62 | + if ( persistenceContext.isEntryFor( entity ) ) { |
| 63 | + LOG.trace( "Ignoring persistent instance passed to replicate()" ); |
| 64 | + //hum ... should we cascade anyway? throw an exception? fine like it is? |
| 65 | + } |
| 66 | + else { |
| 67 | + doReplicate( event, source, entity ); |
| 68 | + } |
67 | 69 | }
|
| 70 | + } |
68 | 71 |
|
69 |
| - EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity ); |
| 72 | + private void doReplicate(ReplicateEvent event, EventSource source, Object entity) { |
| 73 | + final EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity); |
| 74 | + final ReplicationMode replicationMode = event.getReplicationMode(); |
70 | 75 |
|
71 |
| - // get the id from the object |
72 |
| - /*if ( persister.isUnsaved(entity, source) ) { |
73 |
| - throw new TransientObjectException("transient instance passed to replicate()"); |
74 |
| - }*/ |
75 |
| - Object id = persister.getIdentifier( entity, source ); |
| 76 | + // get the id from the object - we accept almost anything at all, |
| 77 | + // except null (that is, even ids which look like they're unsaved) |
| 78 | + final Object id = persister.getIdentifier( entity, source ); |
76 | 79 | if ( id == null ) {
|
77 | 80 | throw new TransientObjectException( "instance with null id passed to replicate()" );
|
78 | 81 | }
|
79 | 82 |
|
80 |
| - final ReplicationMode replicationMode = event.getReplicationMode(); |
81 |
| - |
82 | 83 | final Object oldVersion = replicationMode == ReplicationMode.EXCEPTION
|
83 |
| - ? null //always do an INSERT, and let it fail by constraint violation |
84 |
| - : persister.getCurrentVersion(id, source); //what is the version on the database? |
| 84 | + ? null // always do an INSERT, and let it fail by constraint violation |
| 85 | + : persister.getCurrentVersion( id, source); // what is the version on the database? |
85 | 86 |
|
86 | 87 | if ( oldVersion != null ) {
|
87 | 88 | if ( LOG.isTraceEnabled() ) {
|
88 |
| - LOG.tracev( |
89 |
| - "Found existing row for {0}", |
90 |
| - MessageHelper.infoString( persister, id, event.getFactory() ) |
91 |
| - ); |
| 89 | + LOG.tracev("Found existing row for {0}", |
| 90 | + infoString( persister, id, event.getFactory() ) ); |
92 | 91 | }
|
93 |
| - |
94 |
| - @SuppressWarnings("unchecked") |
95 |
| - final BasicType<Object> versionType = (BasicType<Object>) persister.getVersionType(); |
96 |
| - final Object realOldVersion = persister.isVersioned() ? oldVersion : null; /// HHH-2378 |
97 |
| - boolean canReplicate = replicationMode.shouldOverwriteCurrentVersion( |
98 |
| - entity, |
99 |
| - realOldVersion, |
100 |
| - persister.getVersion( entity ), |
101 |
| - versionType |
102 |
| - ); |
103 |
| - |
104 |
| - // if can replicate, will result in a SQL UPDATE |
105 |
| - // else do nothing (don't even re-associate object!) |
106 |
| - if ( canReplicate ) { |
| 92 | + // If the entity has no version, getCurrentVersion() just returns |
| 93 | + // a meaningless value to indicate that the row exists (HHH-2378) |
| 94 | + final Object realOldVersion = persister.isVersioned() ? oldVersion : null; |
| 95 | + if ( shouldOverwrite( replicationMode, |
| 96 | + persister.getVersion( entity ), realOldVersion, |
| 97 | + persister.getVersionType() ) ) { |
| 98 | + // execute a SQL UPDATE |
107 | 99 | performReplication( entity, id, realOldVersion, persister, replicationMode, source );
|
108 | 100 | }
|
109 | 101 | else if ( LOG.isTraceEnabled() ) {
|
| 102 | + // do nothing (don't even re-associate object!) |
110 | 103 | LOG.trace( "No need to replicate" );
|
111 | 104 | }
|
112 | 105 |
|
113 | 106 | //TODO: would it be better to do a refresh from db?
|
114 | 107 | }
|
115 | 108 | else {
|
116 |
| - // no existing row - do an insert |
| 109 | + // no existing row - execute a SQL INSERT |
117 | 110 | if ( LOG.isTraceEnabled() ) {
|
118 |
| - LOG.tracev( |
119 |
| - "No existing row, replicating new instance {0}", |
120 |
| - MessageHelper.infoString( persister, id, event.getFactory() ) |
121 |
| - ); |
| 111 | + LOG.tracev( "No existing row, replicating new instance {0}", |
| 112 | + infoString( persister, id, event.getFactory() ) ); |
122 | 113 | }
|
123 |
| - |
124 | 114 | final boolean regenerate = persister.isIdentifierAssignedByInsert(); // prefer re-generation of identity!
|
125 | 115 | final EntityKey key = regenerate ? null : source.generateEntityKey( id, persister );
|
126 |
| - |
127 | 116 | performSaveOrReplicate( entity, key, persister, regenerate, replicationMode, source, false );
|
128 | 117 | }
|
129 | 118 | }
|
130 | 119 |
|
| 120 | + private static <T> boolean shouldOverwrite( |
| 121 | + ReplicationMode replicationMode, Object entityVersion, Object realOldVersion, BasicType<T> versionType) { |
| 122 | + return replicationMode.shouldOverwriteCurrentVersion( (T) realOldVersion, (T) entityVersion, versionType ); |
| 123 | + } |
| 124 | + |
131 | 125 | @Override
|
132 | 126 | protected boolean visitCollectionsBeforeSave(
|
133 | 127 | Object entity,
|
@@ -165,7 +159,8 @@ private void performReplication(
|
165 | 159 | EventSource source) throws HibernateException {
|
166 | 160 |
|
167 | 161 | if ( LOG.isTraceEnabled() ) {
|
168 |
| - LOG.tracev( "Replicating changes to {0}", MessageHelper.infoString( persister, id, source.getFactory() ) ); |
| 162 | + LOG.tracev( "Replicating changes to {0}", |
| 163 | + infoString( persister, id, source.getFactory() ) ); |
169 | 164 | }
|
170 | 165 |
|
171 | 166 | new OnReplicateVisitor( source, id, entity, true ).process( entity, persister );
|
|
0 commit comments