J'ai écrit un exemple d'application pour tester la gestion des transactions annotées dans Spring (@Transactional).@Transactional ne fonctionne pas lorsque @Autowired s'applique
fichier de contexte;
<?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/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<tx:annotation-driven />
<context:component-scan base-package="com.test" />
<bean id="playerService" class="com.test.service.PlayerServiceImpl" />
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="dbUtil" class="com.test.util.DbUtil" init-method="initialize">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<context:property-placeholder location="jdbc.properties"/>
PlayerDao haricot
import com.test.model.Player;
import com.test.model.Team;
public interface PlayerDao {
public void insertPlayer(Player player);
public void insertTeam(Team team);
}
mise en œuvre de PlayerDaoImpl
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.test.model.Player;
import com.test.model.Team;
@Repository
public class PlayerDaoImpl implements PlayerDao{
private JdbcTemplate jdbcTemplate;
@Autowired
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
@Transactional (propagation=Propagation.REQUIRED)
public void insertPlayer(Player player){
String insertSql ="INSERT INTO PLAYERS (PLAYER_NAME, DOB, AGE, TEAM_ID) VALUES(?,?,?,?);";
jdbcTemplate.update(insertSql,new Object[]{player.getPlayerName(),player.getDob(), player.getAge(), player.getTeamId()});
}
@Transactional (propagation=Propagation.REQUIRED)
public void insertTeam(Team team){
String insertSql ="INSERT INTO TEAMS (TEAM_ID, TEAM_NAME) VALUES(?,?);";
jdbcTemplate.update(insertSql,new Object[]{team.getTeamId(),team.getTeamName()});
}
}
PlayerService
import com.test.model.Team;
public interface PlayerService {
public void createTeam1(Team team) throws Exception;
public void createTeam2(Team team) throws Exception;
}
PlayerService mise en œuvre
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.test.model.Team;
import com.test.persistence.PlayerDao;
@Service
public class PlayerServiceImpl implements PlayerService{
@Autowired
private PlayerDao playerDao;
public void createTeam1(Team team) throws Exception{
playerDao.insertPlayer(team.getPlayers().get(0));
playerDao.insertPlayer(team.getPlayers().get(1));
playerDao.insertPlayer(team.getPlayers().get(2));
playerDao.insertTeam(team);
}
public void createTeam2(Team team) throws Exception{
playerDao.insertPlayer(team.getPlayers().get(0));
playerDao.insertPlayer(team.getPlayers().get(1));
playerDao.insertTeam(team);
throw new Exception();
}
}
La classe principale;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.test.model.Player;
import com.test.model.Team;
import com.test.service.PlayerService;
public class TestMain {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
PlayerService playerService = (PlayerService) context.getBean("playerService");
Team t1 = new Team();
t1.setTeamId(1);
t1.setTeamName("Team-1");
Player p1 = new Player("Player 1", LocalDate.of(1981,05,02), 1);
Player p2 = new Player("Player 2", LocalDate.of(1983,02,15), 1);
Player p3 = new Player("Player 3", LocalDate.of(1980,12,31), 1);
List<Player> players1 = new ArrayList<Player>();
players1.add(p1);
players1.add(p2);
players1.add(p3);
t1.setPlayers(players1);
Team t2 = new Team();
t2.setTeamId(2);
t2.setTeamName("Team-2");
Player p4 = new Player("Player 4", LocalDate.of(1989,05,02), 1);
Player p5 = new Player("Player 5", null, 1);
List<Player> players2 = new ArrayList<Player>();
players2.add(p4);
players2.add(p5);
t2.setPlayers(players2);
try {
playerService.createTeam1(t1);
playerService.createTeam2(t2);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Transaction fonctionne bien, quand je mets playerDao comme l'une des propriétés du PlayerService dans le fichier de contexte comme ci-dessous (aucun ensemble @Autowired pour playerDao);
<bean id="playerService" class="com.slpl.service.PlayerServiceImpl" >
<property name="playerDao" ref="playerDao" />
</bean>
<bean id="playerDao" class="com.slpl.persistence.PlayerDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
Mais, quand je @Autowired playerDao à la classe PlayerServiceImpl, la transaction n'a pas applique (transaction ne fonctionne pas) et.
Quelle est l'erreur que j'ai commise ici?
Votre transaction doit débuter au niveau du service, elle ne démarre qu'à Dao. Mark Service comme '@ Tansactional' – Rohit
Une raison spécifique d'ajouter @Transactional au niveau de service? – nwGCham
Est-ce que créer une opération atomique d'équipe et de joueur? 'throw new Exception()' dans la méthode de service lorsque votre transaction commence et se termine dans DAO ne provoquera pas une annulation. Qu'entendez-vous par "transaction ne fonctionne pas"? Avez-vous des exceptions ou pas de données dans la base de données? – Rohit