1 /*
2 * Hibernate, Relational Persistence for Idiomatic Java
3 *
4 * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
5 * indicated by the @author tags or express copyright attribution
6 * statements applied by the authors. All third-party contributions are
7 * distributed under license by Red Hat Middleware LLC.
8 *
9 * This copyrighted material is made available to anyone wishing to use, modify,
10 * copy, or redistribute it subject to the terms and conditions of the GNU
11 * Lesser General Public License, as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
16 * for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this distribution; if not, write to:
20 * Free Software Foundation, Inc.
21 * 51 Franklin Street, Fifth Floor
22 * Boston, MA 02110-1301 USA
23 *
24 */
25 package org.hibernate.action;
26
27 import java.io.Serializable;
28
29 import org.hibernate.AssertionFailure;
30 import org.hibernate.HibernateException;
31 import org.hibernate.cache.CacheKey;
32 import org.hibernate.cache.entry.CacheEntry;
33 import org.hibernate.engine.EntityEntry;
34 import org.hibernate.engine.SessionFactoryImplementor;
35 import org.hibernate.engine.SessionImplementor;
36 import org.hibernate.engine.Versioning;
37 import org.hibernate.event.PostInsertEvent;
38 import org.hibernate.event.PostInsertEventListener;
39 import org.hibernate.event.PreInsertEvent;
40 import org.hibernate.event.PreInsertEventListener;
41 import org.hibernate.event.EventSource;
42 import org.hibernate.persister.entity.EntityPersister;
43
44 public final class EntityInsertAction extends EntityAction {
45
46 private Object[] state;
47 private Object version;
48 private Object cacheEntry;
49
50 public EntityInsertAction(
51 Serializable id,
52 Object[] state,
53 Object instance,
54 Object version,
55 EntityPersister persister,
56 SessionImplementor session) throws HibernateException {
57 super( session, id, instance, persister );
58 this.state = state;
59 this.version = version;
60 }
61
62 public Object[] getState() {
63 return state;
64 }
65
66 public void execute() throws HibernateException {
67 EntityPersister persister = getPersister();
68 SessionImplementor session = getSession();
69 Object instance = getInstance();
70 Serializable id = getId();
71
72 boolean veto = preInsert();
73
74 // Don't need to lock the cache here, since if someone
75 // else inserted the same pk first, the insert would fail
76
77 if ( !veto ) {
78
79 persister.insert( id, state, instance, session );
80
81 EntityEntry entry = session.getPersistenceContext().getEntry( instance );
82 if ( entry == null ) {
83 throw new AssertionFailure( "possible nonthreadsafe access to session" );
84 }
85
86 entry.postInsert();
87
88 if ( persister.hasInsertGeneratedProperties() ) {
89 persister.processInsertGeneratedProperties( id, instance, state, session );
90 if ( persister.isVersionPropertyGenerated() ) {
91 version = Versioning.getVersion(state, persister);
92 }
93 entry.postUpdate(instance, state, version);
94 }
95
96 }
97
98 final SessionFactoryImplementor factory = getSession().getFactory();
99
100 if ( isCachePutEnabled( persister, session ) ) {
101
102 CacheEntry ce = new CacheEntry(
103 state,
104 persister,
105 persister.hasUninitializedLazyProperties( instance, session.getEntityMode() ),
106 version,
107 session,
108 instance
109 );
110
111 cacheEntry = persister.getCacheEntryStructure().structure(ce);
112 final CacheKey ck = new CacheKey(
113 id,
114 persister.getIdentifierType(),
115 persister.getRootEntityName(),
116 session.getEntityMode(),
117 session.getFactory()
118 );
119 // boolean put = persister.getCache().insert(ck, cacheEntry);
120 boolean put = persister.getCacheAccessStrategy().insert( ck, cacheEntry, version );
121
122 if ( put && factory.getStatistics().isStatisticsEnabled() ) {
123 factory.getStatisticsImplementor().secondLevelCachePut( getPersister().getCacheAccessStrategy().getRegion().getName() );
124 }
125
126 }
127
128 postInsert();
129
130 if ( factory.getStatistics().isStatisticsEnabled() && !veto ) {
131 factory.getStatisticsImplementor()
132 .insertEntity( getPersister().getEntityName() );
133 }
134
135 }
136
137 private void postInsert() {
138 PostInsertEventListener[] postListeners = getSession().getListeners()
139 .getPostInsertEventListeners();
140 if ( postListeners.length > 0 ) {
141 PostInsertEvent postEvent = new PostInsertEvent(
142 getInstance(),
143 getId(),
144 state,
145 getPersister(),
146 (EventSource) getSession()
147 );
148 for ( int i = 0; i < postListeners.length; i++ ) {
149 postListeners[i].onPostInsert(postEvent);
150 }
151 }
152 }
153
154 private void postCommitInsert() {
155 PostInsertEventListener[] postListeners = getSession().getListeners()
156 .getPostCommitInsertEventListeners();
157 if ( postListeners.length > 0 ) {
158 PostInsertEvent postEvent = new PostInsertEvent(
159 getInstance(),
160 getId(),
161 state,
162 getPersister(),
163 (EventSource) getSession()
164 );
165 for ( int i = 0; i < postListeners.length; i++ ) {
166 postListeners[i].onPostInsert(postEvent);
167 }
168 }
169 }
170
171 private boolean preInsert() {
172 PreInsertEventListener[] preListeners = getSession().getListeners()
173 .getPreInsertEventListeners();
174 boolean veto = false;
175 if (preListeners.length>0) {
176 PreInsertEvent preEvent = new PreInsertEvent( getInstance(), getId(), state, getPersister(), (EventSource)getSession() );
177 for ( int i = 0; i < preListeners.length; i++ ) {
178 veto = preListeners[i].onPreInsert(preEvent) || veto;
179 }
180 }
181 return veto;
182 }
183
184 //Make 100% certain that this is called before any subsequent ScheduledUpdate.afterTransactionCompletion()!!
185 public void afterTransactionCompletion(boolean success) throws HibernateException {
186 EntityPersister persister = getPersister();
187 if ( success && isCachePutEnabled( persister, getSession() ) ) {
188 final CacheKey ck = new CacheKey(
189 getId(),
190 persister.getIdentifierType(),
191 persister.getRootEntityName(),
192 getSession().getEntityMode(),
193 getSession().getFactory()
194 );
195 boolean put = persister.getCacheAccessStrategy().afterInsert( ck, cacheEntry, version );
196
197 if ( put && getSession().getFactory().getStatistics().isStatisticsEnabled() ) {
198 getSession().getFactory().getStatisticsImplementor()
199 .secondLevelCachePut( getPersister().getCacheAccessStrategy().getRegion().getName() );
200 }
201 }
202 postCommitInsert();
203 }
204
205 protected boolean hasPostCommitEventListeners() {
206 return getSession().getListeners().getPostCommitInsertEventListeners().length>0;
207 }
208
209 private boolean isCachePutEnabled(EntityPersister persister, SessionImplementor session) {
210 return persister.hasCache() &&
211 !persister.isCacheInvalidationRequired() &&
212 session.getCacheMode().isPutEnabled();
213 }
214
215 }
216
217
218
219
220
221
222