spring querydsl 我不想开始交易

spring querydsl I don't want start a transaction

实体:

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);
    }
    ......
}

存储库

package com.test.repos

public interface RTestTable extends JpaRepository<TestTable, Long>, QueryDslPredicateExecutor<TestTable> {
}

服务

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 配置

<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" />

我测试了 TestServiceR.handler() 和 TestServiceQuery.handler()。 我认为他们不会开始交易。 但是 class TestServiceR 正在启动事务。 为什么?我如何设置 TestServiceR.handler() 不开始交易。

TestServiceR 调用 RTestTable.findOne 扩展 JpaRepository,后者由 SimpleJpaRepository 实现,后者用 @Transactional(readOnly = true) 注释。因此,交易由 SimpleJpaRepository.

开始

考虑到它不会对应用程序产生不利影响(至少不会太大),您是否有什么特别的原因让您担心交易?如果您不相信,请查看 this Spring Data JPA JIRA issue 的评论历史记录。

如果您仍想覆盖默认行为,您可以将 JPA 存储库初始化为 @EnableJpaRepositories(enableDefaultTransactions = false)(Java 配置)或 <jpa:repositories enable-default-transactions="false" ... />(XML 配置)以防止默认情况下创建交易的默认实现。有关详细信息,请参阅 this Spring Data JPA JIRA issue