简体   繁体   中英

Trying to Get JPA/Hibernate working with REST — TransactionRequiredException: No Transaction is in progress error

I've been trying to get Hibernate / JPA working with my simple Spring 3.2 REST application.

Hibernate/JPA successfully create my table in MySQL, but the transaction fails once it gets into the Repository -- saying no transaction is in progress. I'm really out of my element here and not even sure how to troubleshoot this as it seems most of the code is happening behind the scenes in xml.

Any help much appreciated. UPDATE -- jpaContext.xml

<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">

<context:annotation-config />
<context:component-scan base-package="com.saltcitywifi"></context:component-scan>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="punit" />
    <property name="dataSource" ref="dataSource" />
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" >
            <property name="showSql" value="true" />
        </bean>
    </property>
    <property name="jpaPropertyMap">
        <map>
            <entry key="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
            <entry key="hibernate.hbm2ddl.auto" value="create" />
            <entry key="hibernate.format_sql" value="true" />
        </map>
    </property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />

</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/salt_city_wifi?autoReconnect=true" />
    <property name="username" value="wifi_admin" />
    <property name="password" value="password" />
</bean>

Controller:

@Controller
public class HotSpotController {
@Autowired
private HotSpotService hotSpotService;

@RequestMapping(value = "/hotSpots", method = RequestMethod.GET)
public @ResponseBody
List<HotSpot> getHotSpots() {
    hotSpotService = new HotSpotServiceImpl();
    List<HotSpot> spots = hotSpotService.getAllHotSpots();
    return spots;
}

@RequestMapping(value = "/hotSpot", method = RequestMethod.POST)
public @ResponseBody
HotSpot addHotSpot(@RequestBody HotSpot hotSpot) {
    hotSpotService.addHotSpot(hotSpot);
    return hotSpot;
}

}

Service:

@Service("hotSpotService")
@Transactional
public class HotSpotServiceImpl implements HotSpotService {
@Autowired
private HotSpotRepository hotSpotRepository;
private AtomicLong counter = new AtomicLong();

public List<HotSpot> getAllHotSpots() {
    List<HotSpot> spots = new ArrayList<HotSpot>();
    HotSpot spot;
    for (int i = 0; i < 10; i++) {
        spot = new HotSpot("location " + i, "http://www.url" + i + ".com",
                counter.incrementAndGet());
        spots.add(spot);
    }
    return spots;
}

public HotSpot getHotSpotById(long id) {
    HotSpot spot = new HotSpot("New Spot", "New Url", id);
    return spot;
}

@Transactional
public HotSpot addHotSpot(HotSpot hotSpot) {
    return hotSpotRepository.addHotSpot(hotSpot);

}

}

@Repository("hotSpotRepository")
public class HotSpotRepositoryImpl implements HotSpotRepository {
@PersistenceContext
private EntityManager em;


public HotSpot addHotSpot(HotSpot hotSpot) {
    em.persist(hotSpot);
    em.flush();
    return hotSpot;
}

}

OK I finally figured out what was going on here:

I have two component scanners, one for my controllers in servlet-config.xml and one for my JPA stuff in jpaContext.xml.

They were both scanning basically my whole application:

<context:component-scan base-package="com.saltcitywifi" />

When I forced the component scanner for controllers to only look in the controller package:

<context:component-scan base-package="com.saltcitywifi.controller" />

All of a sudden my requests worked and were processed in the database.

I can only assume since my servlet-config.xml configuration only contains:

<context:component-scan base-package="com.saltcitywifi.controller" />
<mvc:annotation-driven />

That Spring was somehow letting servlet-config.xml register the JPA beans, so the transactional annotations weren't being picked up. This is still confusing to me, so if anyone can help explain why this occurs that would be very helpful. I might just ask another stack overflow question on this subject.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM