Entity:
package com.test.entity
@Entity
@Table(name="TEST_TABLE")
public class TestTable implements HasMapping, PrimaryKey<Long>, Serializable {
public static final String TABLE_NAME = "TEST_TABLE";
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="ID", nullable=false)
private Long id;
@Id
@Column(name="Name", nullable=false)
private String name;
@Temporal(value=TemporalType.TIMESTAMP)
@Column(name="CREATE_TIME", nullable=true)
@CreatedDate
private Date createTime;
@Column(name="CREATE_USER", nullable=true, length=32)
@CreatedBy
private String createUser;
@Temporal(value=TemporalType.TIMESTAMP)
@Column(name="LST_UPD_TIME", nullable=true)
@LastModifiedDate
private Date lstUpdTime;
@Column(name="LST_UPD_USER", nullable=true, length=32)
@LastModifiedBy
private String lstUpdUser;
@Column(name="JPA_VERSION", nullable=false)
@Version
private Integer jpaVersion;
......
}
QPath
package com.test.qpath
@Generated("com.mysema.query.codegen.EntitySerializer")
public class QTestTable extends EntityPathBase<TestTable> {
private static final long serialVersionUID = -1751805455;
public static final QTestTable testTable = new QTestTable("testTable");
public final NumberPath<Long> id = createNumber("id", Long.class);
public final DateTimePath<java.util.Date> createTime = createDateTime("createTime", java.util.Date.class);
public final StringPath createUser = createString("createUser");
public final NumberPath<Integer> jpaVersion = createNumber("jpaVersion", Integer.class);
public final DateTimePath<java.util.Date> lstUpdTime = createDateTime("lstUpdTime", java.util.Date.class);
public final StringPath lstUpdUser = createString("lstUpdUser");
public QTestTable(String variable) {
super(TestTable.class, forVariable(variable));
}
@SuppressWarnings("all")
public QTestTable(Path<? extends TestTable> path) {
super((Class)path.getType(), path.getMetadata());
}
public QTestTable(PathMetadata<?> metadata) {
super(TestTable.class, metadata);
}
......
}
Repository
package com.test.repos
public interface RTestTable extends JpaRepository<TestTable, Long>, QueryDslPredicateExecutor<TestTable> {
}
Service
package com.test.service
@Service
public class TestServiceR() {
@Autowired
private RTestTable rTestTable;
public void handler() {
long id = 1;
TestTable t = rTestTable.findone(id);
}
}
package com.test.service
@Service
public class TestServiceQuery() {
@Autowired
private RTestTable rTestTable;
@PersistenceContext
private EntityManager em;
private QTestTable qTestTable = QTestTable.testTable;
public void handler() {
long id = 1;
JPAQuery query = new JPAQuery(em);
TestTable t = query.from(qTestTable).where(qTestTable.id.eq(id)).singleResult(qTestTable);
}
}
spring config
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="url" value="#{env.jdbcUrl}" />
<property name="username" value="#{env.jdbcUsername}" />
<property name="password" value="#{env.jdbcPassword}" />
<property name="initialSize" value="1" />
<property name="minIdle" value="#{env['jdbcMinIdle'] ?: 2 }" />
<property name="maxActive" value="#{env['jdbcMaxActive'] ?: 20}" />
<property name="minEvictableIdleTimeMillis" value="#{env['jdbcMinEvictableIdleTimeMillis'] ?: 1800000}" />
<property name="validationQuery" value="#{env['jdbcTestSql']}" />
<property name="testWhileIdle" value="#{env['jdbcTestWhileIdle']?: false}" />
<property name="testOnBorrow" value="#{env['jdbcTestOnBorrow']?: true}" />
<property name="testOnReturn" value="#{env['jdbcTestOnReturn']?: false}" />
<property name="poolPreparedStatements" value="false" />
<property name="maxPoolPreparedStatementPerConnectionSize" value="-1" />
<property name="filters" value="mergeStat,slf4j" />
<property name="connectionProperties" value="druid.stat.slowSqlMillis=1500;druid.stat.logSlowSql=true" />
<property name="timeBetweenLogStatsMillis" value="900000" />
</bean>
<bean id="emf"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="default" />
<property name="packagesToScan">
<list>
<value>com.sunline.ccs.infrastructure.shared.model</value>
</list>
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="#{env['jpaDatabaseType']?:'DEFAULT'}" />
<property name="showSql" value="#{env['jpaShowSql']?:false}" />
</bean>
</property>
</bean>
<bean id="sessionFactory" factory-bean="emf" factory-method="getSessionFactory" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emf" />
</bean>
<tx:annotation-driven mode="aspectj"
transaction-manager="transactionManager" />
<jpa:repositories base-package="com.test.repos" />
I test TestServiceR.handler() and TestServiceQuery.handler(). I think they don't start a transaction. but class TestServiceR are start a transaction. why? how can i set TestServiceR.handler() don't start a transaction.
TestServiceR
calls RTestTable.findOne
which extends JpaRepository
, which is implemented by SimpleJpaRepository
, which is annotated with @Transactional(readOnly = true)
. So, the transaction is started by SimpleJpaRepository
.
Is there a particular reason why you are worried about the transaction, given that it does not affect the application adversely (at least not much)? See the comment history for this Spring Data JPA JIRA issue if you are not convinced.
If you still want to override the default behaviour, you can initialise JPA repositories as @EnableJpaRepositories(enableDefaultTransactions = false)
(Java configuration) or <jpa:repositories enable-default-transactions="false" ... />
(XML configuration) to prevent the default implementation from creating transactions by default. See this Spring Data JPA JIRA issue for more details.