I have a very simple one-to-one test that doesn't seem to be
working. The test executes three transactions each with a new entity
manager. In the first tx, I create two bean and persist them. In
the second transaction, I find the two beans again and set the
relationship property. In the third transaction, I find the beans
again, and verify the property is set. Between each tx, I dump the
contents of the tables and OpenJPA is never setting the fk column.
I've tried calling every method on entity manager to sync and flush
the beans in the second transaction, but OpenJPA never seem to update
my bean. I assume my code is wrong as this this is fairly common
operation, so what am I doing wrong?
The test code, beans, and mapping file follow this message.
Thanks,
-dain
--------------------
-- OneToOneTest.java
--------------------
import junit.framework.TestCase;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.openejb.persistence.PersistenceUnitInfoImpl;
import org.apache.openjpa.persistence.PersistenceProviderImpl;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.spi.PersistenceProvider;
import javax.persistence.spi.PersistenceUnitTransactionType;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Collections;
import java.util.HashMap;
import java.util.Properties;
public class OneToOneTest extends TestCase {
private DataSource nonJtaDs;
private EntityManagerFactory entityManagerFactory;
public void setUp() throws Exception {
super.setUp();
// init databases
nonJtaDs = createNonJtaDataSource();
// create persistence unit
PersistenceUnitInfoImpl unitInfo = new
PersistenceUnitInfoImpl();
unitInfo.setPersistenceUnitName("FOO");
unitInfo.setPersistenceProviderClassName
(PersistenceProviderImpl.class.getName());
unitInfo.setClassLoader(getClass().getClassLoader());
unitInfo.setExcludeUnlistedClasses(false);
unitInfo.setNonJtaDataSource(nonJtaDs);
unitInfo.setMappingFileNames(Collections.singletonList("META-
INF/test-mappings.xml"));
unitInfo.setTransactionType
(PersistenceUnitTransactionType.RESOURCE_LOCAL);
Properties properties = new Properties();
properties.put("openjpa.jdbc.SynchronizeMappings",
"buildSchema(ForeignKeys=true)");
unitInfo.setProperties(properties);
// create OpenJPA EntityManagerFactory
PersistenceProvider persistenceProvider = new
PersistenceProviderImpl();
entityManagerFactory =
persistenceProvider.createContainerEntityManagerFactory(unitInfo, new
HashMap());
}
public void testResourceLocal() throws Exception {
EntityManager entityManager =
entityManagerFactory.createEntityManager();
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
Magazine wired = new Magazine();
wired.name = "Wired";
entityManager.persist(wired);
Article thinPill = new Article();
thinPill.name = "The Thin Pill";
entityManager.persist(thinPill);
// wired.coverArticle = thinPill;
transaction.commit();
System.out.println("\nInitial configuration");
dump();
entityManager = entityManagerFactory.createEntityManager();
transaction = entityManager.getTransaction();
transaction.begin();
wired = entityManager.find(Magazine.class, "Wired");
thinPill = entityManager.find(Article.class, "The Thin Pill");
wired.coverArticle = thinPill;
transaction.commit();
System.out.println("\nAfter update of relationship");
dump();
entityManager = entityManagerFactory.createEntityManager();
transaction = entityManager.getTransaction();
transaction.begin();
wired = entityManager.find(Magazine.class, "Wired");
assertNotNull(wired);
assertNotNull(wired.coverArticle);
assertEquals(wired.coverArticle.name, "The Thin Pill");
transaction.commit();
}
private DataSource createNonJtaDataSource() throws Exception {
BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName("org.hsqldb.jdbcDriver");
ds.setUrl("jdbc:hsqldb:mem:JpaTest");
ds.setUsername("sa");
ds.setPassword("");
ds.setMaxActive(100);
ds.setMaxWait(10000);
ds.setTestOnBorrow(true);
return ds;
}
public boolean execute(DataSource ds, String sql) throws
SQLException {
Connection connection = null;
Statement statement = null;
try {
connection = ds.getConnection();
statement = connection.createStatement();
return statement.execute(sql);
} finally {
close(statement);
close(connection);
}
}
protected void dump() throws SQLException {
dumpTable(nonJtaDs, "magazine");
dumpTable(nonJtaDs, "article");
}
public static void dumpTable(DataSource ds, String table) throws
SQLException {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
connection = ds.getConnection();
statement = connection.createStatement();
resultSet = statement.executeQuery("SELECT * FROM " +
table);
ResultSetMetaData setMetaData = resultSet.getMetaData();
int columnCount = setMetaData.getColumnCount();
while(resultSet.next()) {
StringBuilder row = new StringBuilder();
for (int i = 1; i <= columnCount; i++) {
if (i > 1) {
row.append(", ");
}
String name = setMetaData.getColumnName(i);
Object value = resultSet.getObject(i);
row.append(name).append("=").append(value);
}
System.out.println(row);
}
} finally {
close(resultSet);
close(statement);
close(connection);
}
}
private static void close(ResultSet resultSet) {
if (resultSet == null) return;
try {
resultSet.close();
} catch (SQLException e) {
}
}
private static void close(Statement statement) {
if (statement == null) return;
try {
statement.close();
} catch (SQLException e) {
}
}
private static void close(Connection connection) {
if (connection == null) return;
try {
connection.close();
} catch (SQLException e) {
}
}
}
----------------
-- Magazine.java
----------------
public class Magazine {
public String name;
public Article coverArticle;
}
---------------
-- Article.java
---------------
public class Article {
public String name;
}
--------------------
-- test-mappings.xml
--------------------
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
version="1.0">
<entity class="Magazine">
<table name="Magazine"/>
<attributes>
<id name="name">
<column name="name"/>
</id>
<one-to-one name="coverArticle">
<join-column name="cover_article"/>
</one-to-one>
</attributes>
</entity>
<entity class="Article">
<table name="Article"/>
<attributes>
<id name="name">
<column name="name"/>
</id>
</attributes>
</entity>
</entity-mappings>