You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@openjpa.apache.org by Cheng Zhang <ch...@yahoo-inc.com> on 2010/03/04 23:59:58 UTC
any spring user here? RE: unexpected update when using many to many relationship
It seems that there is nothing to do with many-to-many relation. I now believe that it's a Spring issue. Could anybody here who is also using Spring please help me out?
Here is my usage of Spring + OpenJPA.
1. Subject.java
-------------------------------------------------------
package test;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "MC_SUBJECT")
public class Subject {
@Id
@Column(length=64)
private String id;
@Column(length=64)
private String title;
public Subject() {
super();
}
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
public void setTitle(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
}
2. SubjectComponent.java
-------------------------------------------------------
package test;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@Component
public class SubjectComponent {
@PersistenceContext
private EntityManager entityManager;
@Transactional(readOnly=false, rollbackFor=Exception.class)
public void create(Subject subject) {
entityManager.persist(subject);
}
@Transactional(readOnly=true)
public Subject read(String id) {
Subject sub = entityManager.find(Subject.class, id);
return sub;
}
}
3. persistence.xml
-------------------------------------------------------
<?xml version="1.0" encoding="utf-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
<persistence-unit name="MetadataBrowserPersistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>
org.apache.openjpa.persistence.PersistenceProviderImpl
</provider>
<class>test.Subject</class>
</persistence-unit>
</persistence>
4. applicationContext.xml
-------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<!--
Application context definition for PetClinic on JPA.
-->
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
p:driverClassName="${jdbc.driverClassName}" p:url="${jdbc.url}" p:username="${jdbc.username}"
p:password="${jdbc.password}"/>
<bean id="persistenceUnitManager" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="persistenceXmlLocations">
<list>
<value>classpath:META-INF/persistence.xml</value>
</list>
</property>
<property name="defaultDataSource" ref="dataSource"/>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" >
<property name="persistenceUnitManager" ref="persistenceUnitManager"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter"
p:database="${jpa.database}" p:showSql="${jpa.showSql}" p:generateDdl="true"/>
</property>
</bean>
<bean id="entityManager" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
p:entityManagerFactory-ref="entityManagerFactory"/>
<context:annotation-config/>
<tx:annotation-driven transaction-manager="transactionManager" />
<context:component-scan base-package="test"/>
</beans>
5. jdbc.properties
--------------------------------------------------------------------
jdbc.driverClassName=org.hsqldb.jdbcDriver
jdbc.url=jdbc:hsqldb:mem:test-db
jdbc.username=sa
jdbc.password=
jpa.database=HSQL
jpa.showSql=true
6. Test.java
------------------------------------------------------------------
import org.springframework.context.support.ClassPathXmlApplicationContext;
import test.Subject;
import test.SubjectComponent;
public class Test {
public static void main(String[] args) {
ClassPathXmlApplicationContext springContext = new ClassPathXmlApplicationContext("applicationContext.xml");
SubjectComponent component = springContext.getBean(SubjectComponent.class);
Subject subject = new Subject();
subject.setId("a subject");
component.create(subject);
System.out.println("======================");
Subject read = component.read(subject.getId());
System.out.println(read.getId());
}
}
And here is the log:
...................
org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean createNativeEntityManagerFactory
INFO: Building JPA container EntityManagerFactory for persistence unit 'MetadataBrowserPersistenceUnit'
31 MetadataBrowserPersistenceUnit WARN [main] openjpa.Runtime - An error occurred while registering a ClassTransformer with PersistenceUnitInfo: name 'MetadataBrowserPersistenceUnit', root URL [file:/C:/Documents%20and%20Settings/chzhang/allnew/m2m/target/classes/]. The error has been consumed. To see it, set your openjpa.Runtime log level to TRACE. Load-time class transformation will not be available.
313 MetadataBrowserPersistenceUnit INFO [main] openjpa.Runtime - Starting OpenJPA 1.2.2
953 MetadataBrowserPersistenceUnit TRACE [main] openjpa.jdbc.SQL - <t 14706435, conn 9116239> executing prepstmnt 2554341 SELECT SEQUENCE_SCHEMA, SEQUENCE_NAME FROM INFORMATION_SCHEMA.SYSTEM_SEQUENCES
984 MetadataBrowserPersistenceUnit TRACE [main] openjpa.jdbc.SQL - <t 14706435, conn 9116239> [31 ms] spent
984 MetadataBrowserPersistenceUnit TRACE [main] openjpa.jdbc.SQL - <t 14706435, conn 9116239> executing stmnt 4618641 CREATE TABLE MC_SUBJECT (id VARCHAR(64) NOT NULL, title VARCHAR(64), PRIMARY KEY (id))
984 MetadataBrowserPersistenceUnit TRACE [main] openjpa.jdbc.SQL - <t 14706435, conn 9116239> [0 ms] spent
1250 MetadataBrowserPersistenceUnit TRACE [main] openjpa.jdbc.SQL - <t 14706435, conn 9116239> executing prepstmnt 27532487 INSERT INTO MC_SUBJECT (id, title) VALUES (?, ?) [params=(String) a subject, (null) null]
1250 MetadataBrowserPersistenceUnit TRACE [main] openjpa.jdbc.SQL - <t 14706435, conn 9116239> [0 ms] spent
======================
1297 MetadataBrowserPersistenceUnit TRACE [main] openjpa.jdbc.SQL - <t 14706435, conn 9116239> executing prepstmnt 11400638 SELECT t0.title FROM MC_SUBJECT t0 WHERE t0.id = ? [params=(String) a subject]
1297 MetadataBrowserPersistenceUnit TRACE [main] openjpa.jdbc.SQL - <t 14706435, conn 9116239> [0 ms] spent
1297 MetadataBrowserPersistenceUnit TRACE [main] openjpa.jdbc.SQL - <t 14706435, conn 9116239> executing prepstmnt 654830 UPDATE MC_SUBJECT SET title = ? WHERE id = ? [params=(null) null, (String) a subject]
1297 MetadataBrowserPersistenceUnit TRACE [main] openjpa.jdbc.SQL - <t 14706435, conn 9116239> [0 ms] spent
a subject
Very weird!
Cheng
> -----Original Message-----
> From: Cheng Zhang
> Sent: Thursday, March 04, 2010 11:09 AM 无住生什么心?
> To: 'users@openjpa.apache.org'
> Subject: RE: unexpected update when using many to many relationship
>
> Hi Ravi,
>
> Yes, calling getters on Subject within a transaction results in update
> statements. The update is on MC_SUBJECT.
>
> I'm using Spring Transaction for the transaction management.
>
> I will try to consolidate some of my code so you can have a full picture
> how openjpa is used in this project.
>
> Thanks,
> Cheng
>
>
> > -----Original Message-----
> > From: Ravi Palacherla [mailto:ravi.palacherla@oracle.com]
> > Sent: Thursday, March 04, 2010 10:02 AM 无住生什么心?
> > To: users@openjpa.apache.org
> > Subject: RE: unexpected update when using many to many relationship
> >
> > Hi Cheng,
> >
> > >> I just read some Subject records
> > Do you mean calling getters on Subject with in a transaction, results in
> > update statement ?
> > I do not think it is an expected behavior.
> >
> > Is the update statement on "MC_SUBJECT" table ?
> > I understand from the code snippet you pasted; that it a self-
> referential
> > many2many relationship between subject and subject, correct ?
> > I think pasting the code snippet that reads subject records ( actually
> all
> > the code that is called inside the transaction) will help.
> >
> > Also what type of persistence context are you using, extended or
> > transaction ?
> >
> > Regards,
> > Ravi.
> >
> > -----Original Message-----
> > From: Cheng Zhang [mailto:chzhang@yahoo-inc.com]
> > Sent: Thursday, March 04, 2010 10:38 AM
> > To: users@openjpa.apache.org
> > Subject: unexpected update when using many to many relationship
> >
> > Hi,
> >
> >
> >
> > I found that, if I use many-to-many relationship, there will be
> > unexpected update when the transaction is closed.
> >
> >
> >
> > Here is my code,
> >
> >
> >
> > @Entity
> >
> > @Table(name = "MC_SUBJECT")
> >
> > public class Subject implements Serializable {
> >
> > @Id
> >
> > @Column(length=64)
> >
> > private String id;
> >
> >
> >
> > @Column
> >
> > private Date createdDate;
> >
> >
> >
> > @Column
> >
> > private String createdBy;
> >
> >
> >
> > @Column(length=128, nullable=false)
> >
> > private String title;
> >
> >
> >
> > @Column(length=128, nullable=false)
> >
> > private String subjectType;
> >
> >
> >
> > @Column(length=2048)
> >
> > private String description;
> >
> >
> >
> > @Column
> >
> > private Date modifiedDate;
> >
> >
> >
> > @Column
> >
> > private String modifiedBy;
> >
> >
> >
> > @ManyToMany(fetch=FetchType.LAZY)
> >
> > @JoinTable(name = "MC_CHILD_SUBJECT", joinColumns = {
> > @JoinColumn(name = "SUBJECT_KEY") }, inverseJoinColumns = {
> > @JoinColumn(name = "CHILD_SUBJECT_KEY") })
> >
> > private List<Subject> childSubjectCollection;
> >
> >
> >
> > ...... getters and setters
> >
> > }
> >
> >
> >
> > In my code, I just read some Subject records. In the log file, I can see
> > some update statement.
> >
> >
> >
> > However, if I change the many-to-many to one-to-many, everything is fine
> > and no update.
> >
> >
> >
> > Is it expected behavior?
> >
> >
> >
> > Thanks,
> >
> >
> >
> > Cheng
> >
> >
> >
> >