This is not specifically a problem with @Transactional. It is due to the configuration of your <tx:annotation-driven/>
.
Spring uses two different AOP mechanisms: JDK dynamic proxies or CGLIB. JDK dynamic proxies is the default and it works through the use of interfaces at run-time. CGLIB works by generating subclasses at compile-time. If you specify <tx:annotation-driven proxy-target-class="true"/>
, Spring will use CGLIB, and your second @Transactional will fire.
You can read more about the subject here.