8
votes

SimpleJDBCTemplate. - Insérer et récupérer l'identifiant

Je pose les données dans la base de données avec SimpleJDbctemplate.

simpleJdbcTemplate.update("insert into TABLE values(default)");


1 commentaires

Merci de répondre. Oui c'est Oracle.


8 Réponses :


1
votes

Vous devez d'abord interroger le à partir de la séquence appropriée , puis fournissez ce ID dans votre instruction insertion. Aussi simple que cela.

En outre, nous appelons le test d'intégration informatique, au lieu d'un test unitaire, sans doute. Vous aimerez peut-être faire référence à Ce type de thread pour avoir une idée concernant Tests d'intégration et IDS.

[édité après commentaire]

Dans ce cas, éliminez cette gâchette. Et récupérer le ID à partir de la séquence directement, avant de créer un insert .

Eh bien, vous pouvez tirer un Sélectionner ... pour mettre à jour sur la table et saisissez le dernier identifiant et incrémenter que par 1. Si votre ID n'est pas séquentiel, ce que je suppose que je ne serais pas le cas, vous pouvez contenir le Rowid , spécifique à Oracle AFAIK. Puis interroger pour id en utilisant cela. En effet, tout ce genre de travail autour.

Note: Je vous suggère fortement de regarder la poste d'Aaron Digulla. Voir si l'un de ce suffisant.


2 commentaires

L'ID est généré par déclencheur dans la base de données.


La gâchette doit utiliser une séquence au fond de quelque part, je suppose. BTW, ce sont les choses qui font des tests poils.



4
votes

Vous devez gérer manuellement la séquence pour obtenir l'identifiant facilement sans vous attacher à un produit SMBMS spécifique.

Cela signifie que vous devez spécifier un DatafieldMaxValueInCrémenter à votre classe de manutention de la base de données, tout comme vous le faites le plus probablement avec votre DataSource . La définition des haricots devrait ressembler à quelque chose comme ceci (cet exemple est pour PostgreSQL) : xxx

puis lorsque vous avez l'incrémenteur de votre classe, vous pouvez Utilisez-le dans votre code pour obtenir la valeur d'identification un peu comme celle-ci: xxx


0 commentaires

1
votes

Répondre à cette question: qu'essayez-vous de réaliser avec votre test? Vérifiez que la mise à jour fonctionne sans erreur? Que vous obtenez une nouvelle carte d'identité à chaque fois? Que la table existe?

Selon la réponse, vous devez modifier votre test. Si vous voulez juste savoir que la syntaxe de la déclaration est correcte, vous n'avez pas besoin de faire quoi que ce soit, mais exécutez la déclaration (elle organisera une exception s'il y a une erreur en train de faire l'échec du test).

Si vous souhaitez vous assurer d'obtenir une nouvelle carte d'identité à chaque fois, vous devez interroger la séquence deux fois et vérifier que la deuxième valeur est différente de la première.

Si vous souhaitez vérifier qu'une ligne d'une nouvelle pièce d'identité unique est insérée, exécutez simplement l'insert et vérifiez qu'il retourne 1. Si cela fonctionne, vous saurez que la clé primaire (l'ID) n'a pas été violée. et qu'une ligne a été insérée. Par conséquent, l'ajout avec un mécanisme d'identification unique doit fonctionner.

[modifier] Il n'y a aucun moyen de tester une gâchette qui ajoute un identifiant à une nouvelle ligne car Oracle n'a aucun moyen de renvoyer l'identifiant qu'il vient de créer. Vous pouvez lire la séquence mais il n'y a aucune garantie que NextVal-1 vous donnera le même résultat que la scie à déclenchement.

Vous pouvez essayer SELECT (ID) mais qui peut échouer si quelqu'un d'autre insère une autre ligne et l'engage avant de pouvoir exécuter la requête (à l'aide du niveau de transaction par défaut read_commoded ).

Par conséquent, je suggère fortement de me débarrasser de la gâchette et d'utiliser l'algorithme standard en 2 étapes ("Obtenir un nouvel identifiant" plus "d'identifiant") que quiconque utilise. Cela rendra vos tests plus simples et moins fragiles.


4 commentaires

Oui, la question posait des questions. +1. Je recommande fortement la même chose. Excellentes suggestions.


J'ai une implémentation de la conception d'objets temporels (voir page Web Martin Folwer pour plus de détails). J'ai un objet continuum et un objet temporel et une méthode dao.load (continuum.class, continus). Cette méthode me renvoie un objet temporel. Il existe de nombreux objets temporels pouvant être connectés à un objet de contingent. Chaque objet temporel a un continuum à celui-ci. Donc, dans mon test, j'aimerais d'abord mettre l'objet de continuum dans la base de données avec une statetimation d'insertion. Ensuite, je voudrais obtenir l'identifiant de l'objet inséré pour charger l'objet temporel.


Dans ce cas, éliminez cette gâchette. Et récupérer l'identifiant en premier, avant de faire un insert.


J'ai trouvé autre solution. Utilisation de la méthode SimpleJDBCinsert.ExecuteTeTurnkeyKeyKeyKey. Cela fonctionne pour moi comme j'avais besoin. Tanks tout le monde.



5
votes

Avez-vous trouvé la réponse encore? Sinon, essayez d'utiliser SimpleJDBCinsert à la place. Par exemple: xxx

puis récupérez xxx


0 commentaires

4
votes

i Dun pense que c'est aussi difficile que cela semble que cela semble. wil contient l'ID de ligne nouvellement inséré.

acclamations .. !! :)


1 commentaires

J'ai fatigué cela et j'ai eu l'erreur suivante; "Aucun résultat n'a été renvoyé par la requête." Peut-être que je fais quelque chose de mal.



3
votes

Utilisation de NamedParameterjdbctTemplate de clé Vous avez un titulaire de clé. Il résume la génération de clés du SGBD. Vérifiez Créer la méthode.

package info.pello.spring.persistence;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.support.GeneratedKeyHolder;

import java.util.ArrayList;
import java.util.List;

/**
 * 
 */

/**
 * DAO for customer entity
 * @author Pello Xabier Altadill Izura
 * @greetz Blue Mug
 *
 */
public class CustomerDAO {

    // I use both jdbcTemplate/namedParameterJdbcTemplate depending on needs
    private JdbcTemplate jdbcTemplate;
    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
    private final static String CREATE_SQL = "insert into customer (name,address,email) values(:name,:address,:email)";

    /**
     * gets Customer data from DataBase
     * @param customerId
     * @return
     */
    public Customer read (int customerId) {
        Customer customer = null;

        return customer;
    } 

    /**
     * gets all Customer data from DataBase
     * @return list of customers
     */
    public List<Customer> readAll () {

        List<Customer> customerList = new ArrayList<Customer>();

        return customerList;
    } 

    /**
     * creates new Customer
     * @param newCustomer
     * @return
     */
    public int create (Customer newCustomer) {
        GeneratedKeyHolder generatedKeyHolder = new GeneratedKeyHolder();

        MapSqlParameterSource namedParameters = new MapSqlParameterSource();
        namedParameters.addValue("name", newCustomer.getName());
        namedParameters.addValue("address", newCustomer.getAddress());
        namedParameters.addValue("email", newCustomer.getEmail());

        namedParameterJdbcTemplate.update(CREATE_SQL,
                            namedParameters,
                            generatedKeyHolder);

        newCustomer.setId(generatedKeyHolder.getKey().intValue());
        return newCustomer.getId();
    }

    /**
     * updates customer information 
     * @param customer
     * @return
     */
    public int update (Customer customer) {
        int result = 0;


        return result;
    }

    /**
     * delete customer  
     * @param customerId
     * @return
     */
    public int delete (int customerId) {

        int result = 0;


        return result;
    }

    /**
     * @return the jdbcTemplate
     */
    public JdbcTemplate getJdbcTemplate() {
        return jdbcTemplate;
    }

    /**
     * @param jdbcTemplate the jdbcTemplate to set
     */
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    /**
     * @return the namedParameterJdbcTemplate
     */
    public NamedParameterJdbcTemplate getNamedParameterJdbcTemplate() {
        return namedParameterJdbcTemplate;
    }

    /**
     * @param namedParameterJdbcTemplate the namedParameterJdbcTemplate to set
     */
    public void setNamedParameterJdbcTemplate(
            NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
        this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
    }


}


1 commentaires

Pour moi à l'aide du titulaire de la clé ne renvoie que la valeur de la séquence réelle. Le code comme indiqué produit une exception: org.springframework.dao.datareRevalfailureException: la clé générée n'est pas du type numérique pris en charge. Impossible de lancer [oracle.sql.rowid] à [java.lang.number] .



1
votes

SimpleJDbCtemplate est obsolète en faveur de NamedParameterjdbCtemplate.

pello x a la bonne réponse, mais sa soumission est trop encombrante pour comprendre. Simplifié: p>

Si vous avez une table très simple appelée échantillon avec une colonne appelée nom et une clé primaire générée appelée ID de type Bigint: P>

MapSqlParameterSource namedParameters = new MapSqlParameterSource().addValue("name", name);

KeyHolder keyHolder = new GeneratedKeyHolder();
int numberOfAffectedRows = namedParameterJdbcTemplate.update("insert into SAMPLE(name) values(:name)", namedParameters, keyHolder);

return numberOfAffectedRows == 1 ? keyHolder.getKey().longValue() : -1L;


0 commentaires

0
votes

avec jdbctemplate code> code> Vous pouvez utiliser sa méthode code> mise à jour code> avec un préparéStatementCreator code> et un Tholder de fabrication code> pour tenir le primaire Touche de la ligne nouvellement insérée.

public class SomeDao(){
   @Autowired
   private JdbcTemplate jdbcTemplate;
   //example of a insertion returning the primary key
   public long save(final String name){
       final KeyHolder holder = new GeneratedKeyHolder();//the newly generated key will be contained in this Object
       jdbcTemplate.update(new PreparedStatementCreator() {
      @Override
      public PreparedStatement createPreparedStatement(final Connection connection) throws SQLException {
        final PreparedStatement ps = connection.prepareStatement("INSERT INTO `names` (`name`) VALUES (?)",
            Statement.RETURN_GENERATED_KEYS);
        ps.setString(1, name);
        return ps;
      }
    }, holder);
    return holder.getKey().longValue();//the primary key of the newly inserted row
   }
}


0 commentaires