mirror of https://github.com/apache/openjpa.git
OPENJPA-2051: Change to ensure entities are properly cascaded after a flush.
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@1186903 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
16c76a0870
commit
c8a84fd37d
|
@ -73,6 +73,8 @@ public class Compatibility {
|
|||
|
||||
private boolean _useListAttributeForArrays = false;
|
||||
private boolean _metaFactoriesAreStrict = false;
|
||||
private boolean _resetFlushFlagForCascadePersist = true;//OPENJPA-2051
|
||||
|
||||
|
||||
/**
|
||||
* Whether to require exact identity value types when creating object
|
||||
|
@ -666,4 +668,32 @@ public class Compatibility {
|
|||
public void setMetaFactoriesAreStrict(boolean metaFactoriesAreStrict) {
|
||||
_metaFactoriesAreStrict = metaFactoriesAreStrict;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether OpenJPA should reset the internal state (flush flag) when cascading a persist to another
|
||||
* Entity. That is, when a flush is performed, OpenJPA keep state to indicate the flush has been
|
||||
* performed. In certain cascade persist scenarios the fact that a flush has been performed prior to
|
||||
* a cascade persist can cause certain entities to not be written to the database given the prior
|
||||
* flush. This property, when set, will cause the flush flag to be reset in cascade scenarios. For more
|
||||
* details see JIRA OPENJPA-2051
|
||||
*
|
||||
* @since 2.0.x
|
||||
*/
|
||||
public boolean getResetFlushFlagForCascadePersist(){
|
||||
return _resetFlushFlagForCascadePersist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether OpenJPA should reset the internal state (flush flag) when cascading a persist to another
|
||||
* Entity. That is, when a flush is performed, OpenJPA keep state to indicate the flush has been
|
||||
* performed. In certain cascade persist scenarios the fact that a flush has been performed prior to
|
||||
* a cascade persist can cause certain entities to not be written to the database given the prior
|
||||
* flush. This property, when set, will cause the flush flag to be reset in cascade scenarios. For more
|
||||
* details see JIRA OPENJPA-2051
|
||||
*
|
||||
* @since 2.0.x
|
||||
*/
|
||||
public void setResetFlushFlagForCascadePersist(boolean b){
|
||||
_resetFlushFlagForCascadePersist = b;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4109,7 +4109,10 @@ public class BrokerImpl
|
|||
lock();
|
||||
try {
|
||||
switch (status) {
|
||||
case STATUS_INIT:
|
||||
case STATUS_INIT:
|
||||
if (_compat.getResetFlushFlagForCascadePersist()){//OPENJPA-2051
|
||||
_flags &= ~FLAG_FLUSHED;
|
||||
}
|
||||
_cache.add(sm);
|
||||
break;
|
||||
case STATUS_TRANSIENT:
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.openjpa.persistence.cascade;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
|
||||
@Entity
|
||||
public class Edge {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private long oid;
|
||||
|
||||
@ManyToOne(cascade = CascadeType.ALL)
|
||||
@JoinColumn(name = "SOURCE_OID")
|
||||
private Vertex source;
|
||||
|
||||
@ManyToOne(cascade = CascadeType.ALL)
|
||||
@JoinColumn(name = "TARGET_OID")
|
||||
private Vertex target;
|
||||
|
||||
protected Edge() {
|
||||
}
|
||||
|
||||
Edge( Vertex src ) {
|
||||
this();
|
||||
this.source = src;
|
||||
}
|
||||
|
||||
public void setTarget( Vertex node ) {
|
||||
this.target = node;
|
||||
}
|
||||
|
||||
public long getOid() {
|
||||
return oid;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.openjpa.persistence.cascade;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityTransaction;
|
||||
import javax.persistence.NoResultException;
|
||||
import javax.persistence.TypedQuery;
|
||||
|
||||
import org.apache.openjpa.persistence.OpenJPAEntityManager;
|
||||
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
|
||||
|
||||
public class TestMultiCascadePersist extends SingleEMFTestCase {
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
setUp(DROP_TABLES, Vertex.class, VertexType.class, Edge.class);
|
||||
}
|
||||
|
||||
public void testSingleTransaction() {
|
||||
OpenJPAEntityManager em = emf.createEntityManager();
|
||||
EntityTransaction tx = em.getTransaction();
|
||||
|
||||
tx.begin();
|
||||
|
||||
//The flush is important to the rest of the test. If this
|
||||
//is removed, the test works as expected. While the flush
|
||||
//at this point in the test may seem odd/unnecessary, it
|
||||
//is more clear to perform a flush directly rather than
|
||||
//something (e.g. query) which would cause a flush under
|
||||
//the covers. See OPENJPA-2051 for more details.
|
||||
em.flush();
|
||||
|
||||
VertexType defaultType = new VertexType( "default" );
|
||||
VertexType specialType = new VertexType( "special" );
|
||||
|
||||
em.persist(defaultType);
|
||||
em.persist(specialType);
|
||||
|
||||
Vertex src = new Vertex( defaultType );
|
||||
Vertex target = new Vertex( specialType );
|
||||
|
||||
Edge t = src.newEdge( target );
|
||||
assertNotNull( t );
|
||||
|
||||
em.persist(src);
|
||||
|
||||
tx.commit();
|
||||
|
||||
TypedQuery<Edge> q = em.createQuery( "SELECT t FROM Edge t", Edge.class );
|
||||
List<Edge> resultList = q.getResultList();
|
||||
|
||||
assertEquals( 1, resultList.size() );
|
||||
assertEquals( 2, findAllVertexType(em).size() );
|
||||
if (emf.getConfiguration().getCompatibilityInstance().getResetFlushFlagForCascadePersist()){
|
||||
assertEquals( 2, findAllVertex(em).size() );
|
||||
}
|
||||
else{
|
||||
//There *should* be 2 Vertex....but by default we can not fix this without a
|
||||
//compatibility flag.
|
||||
assertEquals( 1, findAllVertex(em).size() );
|
||||
}
|
||||
}
|
||||
|
||||
public VertexType findVertexTypeByName(EntityManager em, String name ) {
|
||||
try {
|
||||
TypedQuery<VertexType> query = em.createNamedQuery( "VertexType.findByName",
|
||||
VertexType.class );
|
||||
query.setParameter( 1, name );
|
||||
return query.getSingleResult();
|
||||
} catch ( NoResultException nre ) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public List<VertexType> findAllVertexType(EntityManager em) {
|
||||
try {
|
||||
TypedQuery<VertexType> query = em.createNamedQuery( "VertexType.findAll",
|
||||
VertexType.class );
|
||||
return query.getResultList();
|
||||
} catch ( NoResultException nre ) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
public List<Vertex> findAllVertex(EntityManager em) {
|
||||
try {
|
||||
TypedQuery<Vertex> query = em.createNamedQuery( "Vertex.findAll",
|
||||
Vertex.class );
|
||||
return query.getResultList();
|
||||
} catch ( NoResultException nre ) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.openjpa.persistence.cascade;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.OneToMany;
|
||||
|
||||
|
||||
@Entity
|
||||
@NamedQueries({
|
||||
@NamedQuery(name = "Vertex.findByName",
|
||||
query = "SELECT n FROM Vertex n where n.type.name=?1"),
|
||||
@NamedQuery(name = "Vertex.findAll", query = "SELECT n FROM Vertex n") })
|
||||
public class Vertex {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private long oid;
|
||||
|
||||
@OneToMany(mappedBy = "source", cascade = CascadeType.ALL)
|
||||
private List<Edge> outgoing;
|
||||
|
||||
@OneToMany(mappedBy = "target", cascade = CascadeType.ALL)
|
||||
private List<Edge> incoming;
|
||||
|
||||
@ManyToOne(cascade = CascadeType.ALL)
|
||||
@JoinColumn(name = "TYPE_OID")
|
||||
private VertexType type;
|
||||
|
||||
protected Vertex() {
|
||||
this.incoming = new ArrayList<Edge>();
|
||||
this.outgoing = new ArrayList<Edge>();
|
||||
}
|
||||
|
||||
public Vertex( VertexType type ) {
|
||||
this();
|
||||
this.type = type;
|
||||
type.instances.add( this );
|
||||
}
|
||||
|
||||
public Edge newEdge( Vertex target ) {
|
||||
Edge t = new Edge( this );
|
||||
outgoing.add( t );
|
||||
t.setTarget( target );
|
||||
return t;
|
||||
}
|
||||
|
||||
public long getOid() {
|
||||
return oid;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.openjpa.persistence.cascade;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.OneToMany;
|
||||
|
||||
@Entity
|
||||
@NamedQueries({
|
||||
@NamedQuery(name = "VertexType.findByName",
|
||||
query = "SELECT t FROM VertexType t where t.name=?1"),
|
||||
@NamedQuery(name = "VertexType.findAll",
|
||||
query = "SELECT t FROM VertexType t") })
|
||||
public class VertexType {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private long oid;
|
||||
|
||||
@OneToMany(mappedBy = "type", cascade = CascadeType.ALL)
|
||||
List<Vertex> instances;
|
||||
|
||||
private String name;
|
||||
|
||||
protected VertexType() {
|
||||
this.instances = new ArrayList<Vertex>();
|
||||
}
|
||||
|
||||
public VertexType( String name ) {
|
||||
this();
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public long getOid() {
|
||||
return oid;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue