È possibile configurare aspetto load-time tessendo
Ecco l'esempio di base come farlo
contesto Primavera
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="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-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd">
<context:component-scan base-package="org.foo.bar" />
<context:annotation-config />
<context:load-time-weaver />
<tx:annotation-driven mode="aspectj" proxy-target-class="true"/>
<jdbc:embedded-database id="dataSource">
<jdbc:script location="classpath:schema.sql"/>
</jdbc:embedded-database>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="annotatedClasses">
<list>
<value>org.foo.bar.MyEntity</value>
</list>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
</beans>
classe Entity
pacchetto org.foo.bar;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "ENTITY")
public class MyEntity {
@Id
private long id;
private String name;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("MyEntity");
sb.append("{id=").append(id);
sb.append(", name='").append(name).append('\'');
sb.append('}');
return sb.toString();
}
}
classe Dao
pacchetto org.foo.bar;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.Iterator;
import java.util.NoSuchElementException;
@Component
public class MyEntityDao implements Iterable<MyEntity> {
@Autowired
private SessionFactory sessionFactory;
@Override
public Iterator<MyEntity> iterator() {
return new Iterator<MyEntity>() {
private int num = 0;
private MyEntity item;
@Override
@Transactional(readOnly = true)
public boolean hasNext() {
item = getEntity();
return item != null;
}
@Override
@Transactional(readOnly = true)
public MyEntity next() {
try {
if(item == null) {
item = getEntity();
if(item == null) {
throw new NoSuchElementException();
}
}
return item;
} finally {
item = null;
}
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
private MyEntity getEntity() {
final Criteria criteria = getCurrentSession().createCriteria(MyEntity.class);
criteria.setFirstResult(num++);
criteria.setMaxResults(1);
return (MyEntity) criteria.uniqueResult();
}
};
}
public Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
}
SQL
drop table ENTITY if exists
create table ENTITY (id bigint generated by default as identity (start with 1), name varchar(255), primary key (id))
insert into ENTITY (name) values ('Entity1')
insert into ENTITY (name) values ('Entity2')
insert into ENTITY (name) values ('Entity3')
Unità di prova
pacchetto org.foo.bar;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.junit.Assert.assertEquals;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
"classpath:applicationContext.xml"
})
public class MyEntityDaoTest {
@Autowired
private MyEntityDao dao;
@Test
public void testDao() throws Exception {
int count = 0;
for(MyEntity a : dao) {
count++;
}
assertEquals(3, count);
}
}
Ecco il mio pom.xml http://maven.apache.org/xsd/maven-4.0.0.xsd "> 4.0.0
<groupId>org.foo.bar</groupId>
<artifactId>spring-aspectj-hibernate</artifactId>
<version>1.0</version>
<properties>
<spring.version>3.1.1.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-instrument</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.12</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.1.1.Final</version>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>1.8.0.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Dopo tutto è necessario eseguire JVM con il seguente argomento -javaagent:<PATH-TO>/spring-instrument-{vertion}.jar
. Per evitare di aggiungere l'argomento -javaagent
può anche configurare l'aspetto della tessitura in compile-time.
Grazie per la risposta, ho provato prima di chiedere senza successo. E non voglio che il chiamante sia responsabile della gestione delle transazioni perché non desidero @Transactional nel mio livello di servizio. –
potrebbe essere possibile eseguire alcune patch in 'getCurrentSession()' come getCurrentSession() da sessionFactory se non disponibile, quindi utilizzare 'openSession()', naturalmente è necessario chiuderlo manualmente se si apre una nuova sessione. –
ha funzionato :-) comunque, aspettiamo di vedere se c'è un altro suggerimento –