Réinitialiser un id d'un compteur chaque année

Signaler
Messages postés
186
Date d'inscription
mardi 10 mai 2016
Statut
Membre
Dernière intervention
20 février 2020
-
deep_sea
Messages postés
186
Date d'inscription
mardi 10 mai 2016
Statut
Membre
Dernière intervention
20 février 2020
-
Bonjour ,
Je suis entraîne de développer une application J2EE
Les outils : Java bean entity manager , JSF ,XHTML
Base de donnée : MariaDB

le problème est le suivant :
je voulais réinitialiser un compteur chaque nouvelle année c a d pour chaque demande saisie:
01 2019
02 2019

120 2019

en 2020
1 2020
en principe j'ai la table qui contient les demandes

CREATE TABLE IF NOT EXISTS `Demande` (
  `id_demande` int(6) NOT NULL AUTO_INCREMENT,
  `dt_demande` date DEFAULT NULL,
  `ref` varchar(8) DEFAULT NULL,
  `id_compteur` int(6) DEFAULT NULL,
  [/contents/1055-sql-contraintes-d-integrite PRIMARY KEY] (`id_demande`)

) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;



La table qui gère incrémentation :

CREATE TABLE IF NOT EXISTS `compteur_demande` (
  `id` int(6) NOT NULL AUTO_INCREMENT,
  `id_demande` int(6) DEFAULT NULL,
  `dt_demande` date NOT NULL
  PRIMARY KEY (`id` , `dt_demande` ),

  KEY `FK_compteurr_demande` (`id_demande`),
  CONSTRAINT `FK_compteur_compteur_demande` FOREIGN KEY (`id_demande`) REFERENCES `demande` (`id_demande`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;


Les classes JAVA

@Entity
@Table(name = "compteur_demande")
@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "Compteurdemande.findAll", query = "[/contents/1068-sql-commande-select SELECT] c FROM compteur_demande c"),
    @NamedQuery(name = "Compteurdemande.findById", query ="SELECT c FROM compteur_demande c WHERE c.id = :id"),
    @NamedQuery(name = "Compteurdemande.findByDtdemande", query = "SELECT c FROM compteur_demande c WHERE c.dtdemande = :dtdemande")
})
public class compteur_demande implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id")
    private Integer id;
    @JoinColumn(name = "id_demande", referencedColumnName = "id_demande")
    @ManyToOne
    private Demande iddemande;
    @ManyToOne
    private Demande dt_demande;
 

    public compteur_demande() {
    }

    public compteur_demande(Integer id) {
        this.id = id;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Demande getIdDemande() {
        return iddemande;
    }

    public void setIddemande(Demande iddemande) 
    {
        this.iddemande = iddemande;
    }
    public Demande getdt_demande()
    {
        return  dt_demande;
    }
    public void setdt_demande(Demande dt_demande)
    {
        this.dt_demande = dt_demande;
    }
    
    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof compteur_demande)) {
            return false;
        }
        compteur_demande other = (compteur_demande) object;
        if ((this.id == null && other.id != null) ||(this.id != null && !this.id.equals(other.id))||this.dt_demande!=null && !this.dt_demande.equals(other.dt_demande)) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "models.compteur_demande[ id=" + id + " ]";
    }
    
}


La classe Demande contient les attributs et le constructeurs ...

Pour les méthodes j'ai programmer deux méthode

--> L'une qui récupère le dernier id :
 public Integer maxIdCompte(){
        try {
            TypedQuery<Integer> query = em.createQuery("SELECT MAX(c.id) FROM compteur_demande c", Integer.class);
 
            
         
            if( (query.getSingleResult() != null))
            {
                
                 return query.getSingleResult();
                        
            }

                                    
            else
            {
              return null;   
            }    
               
            
        } catch (Exception e) {
            return null;
        }
    }


et une autre pour mettre a jour le compteur



    public Integer reinitialise()
    {
        try
        {
          TypedQuery<Integer> query2 = em.createQuery("UPDATE compteur_demande c set c.id =1", Integer.class);  
             
            if(query2.getSingleResult() != null)
             {
             return query2.getSingleResult();
             }
                    else
            {
              return null;   
            }    
               
                 
        }
        catch (Exception e) 
        {
            return null;
        }
    }
      


Le problème
je n'arrive pas a insérer la date demande (dt_demande) dans la table compteur_demande sachant que j'ai réussie a insérer id_demande et aussi le compteur ne réinitialise pas

merci de m'orienter

3 réponses

Messages postés
16110
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
13 février 2020
2 532
Bonjour,

En base de données il vaut mieux avoir un identifiant technique (autogénéré) en plus de ton identifiant fonctionnel (année+incrément), le premier étant géré en SQL, le second en Java.

Question : ton "compteur" pour l'année peut-il avoir des "trous" ? C'est à dire que si 2019-42 existe et que 2019-44 existe aussi, la valeur 2019-43 doit elle obligatoirement exister ?

Après, il y a plusieurs manières de faire, plus ou moins complexes, plus ou moins fiables, cela dépend aussi de l'architecture de ton application (en particulier pour la gestion de la concurrence)
deep_sea
Messages postés
186
Date d'inscription
mardi 10 mai 2016
Statut
Membre
Dernière intervention
20 février 2020

Bonjour ,
c'est un ordre par année c a d
40 2019
41 2019
42 2019
43 2019

pour moi c'est une application web basé sur le modele MVC
KX
Messages postés
16110
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
13 février 2020
2 532 > deep_sea
Messages postés
186
Date d'inscription
mardi 10 mai 2016
Statut
Membre
Dernière intervention
20 février 2020

Que ce soit une application web basé sur le modele MVC ne changera rien, il faut travailler uniquement sur les data.

Ma question concernant les "trous" est très importante pour t'orienter au mieux car ce serait une contrainte très forte.
Typiquement un auto-incrément géré par la base de données peut avoir des trous et faire mieux est bien plus complexe.

Une première solution, plutôt solide, est de mettre en place un trigger qui se déclenchera à l'insertion de la donnée et dont le travail sera de calculer l'identifiant à partir de la date courante.

Voir : https://mariadb.com/kb/en/trigger-overview/
Messages postés
186
Date d'inscription
mardi 10 mai 2016
Statut
Membre
Dernière intervention
20 février 2020

Bonjour ,
je vais vous expliquer ce que je pense
enfaîte je voulais incrémenter mon compteur chaque année
mais lorsque l'année change le compteur doit être réinitialiser a 1
pour la proposition de mettre un trigger c'est vraiment solide mais je voulais que ce dernier se déclenchera à l'insertion de la donnée et dont le travail sera de calculer l'identifiant à partir de la date demande et ne pas la date courante .

le problème je n arrive pas a exprimer mon idée


CREATE TRIGGER RESETCOUNTER
BEFORE INSERT ON compteur_demande
BEGIN
[/contents/1068-sql-commande-select select]  max(id) as lastid ,YEAR(dt_demande) as lastdate from compteur_demande
IF( old.lastdate <> new.dt_demande  )
UPDATE compteur_demande  set id = 1
END IF
END
KX
Messages postés
16110
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
13 février 2020
2 532
Bonjour,

Voici un exemple (testé avec MySql, mais MariaDB est assez proche)

DROP TABLE IF EXISTS demande;

CREATE TABLE demande (
  id_demande BIGINT NOT NULL AUTO_INCREMENT,
  annee_demande SMALLINT NOT NULL DEFAULT 0,
  numero_demande INT NOT NULL DEFAULT 0,
  text_demande VARCHAR(255) NOT NULL,
  PRIMARY KEY (id_demande),
  UNIQUE unique_numero_par_annee (annee_demande, numero_demande)
);

DELIMITER $
CREATE TRIGGER numero_demande_trigger BEFORE INSERT ON demande
FOR EACH ROW
BEGIN
    DECLARE annee_actuelle SMALLINT;
    DECLARE max_numero INT;
    
    SET @annee_actuelle = YEAR(CURRENT_DATE);
    SET @max_numero = (SELECT COALESCE(MAX(numero_demande), 0) FROM demande WHERE annee_demande=@annee_actuelle);   
    
    SET NEW.annee_demande = @annee_actuelle;
    SET NEW.numero_demande = @max_numero + 1;
END$
DELIMITER ;

INSERT INTO demande (text_demande) VALUES ('un'), ('deux'), ('trois');

SELECT * FROM demande;


Résultat :
id_demande  annee_demande  numero_demande  text_demande
1           2020           1               un          
2           2020           2               deux        
3           2020           3               trois        
Messages postés
186
Date d'inscription
mardi 10 mai 2016
Statut
Membre
Dernière intervention
20 février 2020

Bonjour
c'est il possible de m'aider dans cette fonction , enfaîte je veux comparer l'année de lademande saisie a travers l'instance dem avec le résultat de la requête :
ci après ma logique
si ils sont égaux alors je retourne le max de id
si l'année de la demande saisie != de l'année retourné par la requête alors 1(réinitialiser le compteur a 1)


Le problème même l'année change ( ne sont pas égaux) le compteur incrémente a chaque fois
voici ma fonction :

public Integer maxIde(){
        try {
            CompteurDemande dem= new CompteurDemande ();

           TypedQuery<Integer>  max_date = em.createQuery("[/contents/1068-sql-commande-select SELECT] year_demande FROM CompteurDemande c ORDER BY  year_demande DESC LIMIT 1", Integer.class);

            System.out.println(max_date);

            TypedQuery<Integer> query = em.createQuery("SELECT MAX(c.id) FROM CompteurDemande c ORDER BY  year_demande DESC LIMIT 1", Integer.class);

             System.out.println(query);

            if(query.getSingleResult() != null  && max_date.getSingleResult() != null)
            {
                 System.out.println("OK");

         if ( max_date.getSingleResult().equals(dem.getyeardemande()))
         {
                return query.getSingleResult();
            
         }
         else
         {
             return 1;

         }
                
            }
               else
                return null;