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

Fermé
deep_sea Messages postés 201 Date d'inscription mardi 10 mai 2016 Statut Membre Dernière intervention 10 décembre 2022 - Modifié le 20 janv. 2020 à 11:12
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 - 24 févr. 2020 à 11:47
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
A voir également:

4 réponses

KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015
20 janv. 2020 à 15:13
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)
0
deep_sea Messages postés 201 Date d'inscription mardi 10 mai 2016 Statut Membre Dernière intervention 10 décembre 2022 1
22 janv. 2020 à 09:11
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
0
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015 > deep_sea Messages postés 201 Date d'inscription mardi 10 mai 2016 Statut Membre Dernière intervention 10 décembre 2022
22 janv. 2020 à 16:27
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/
0
deep_sea Messages postés 201 Date d'inscription mardi 10 mai 2016 Statut Membre Dernière intervention 10 décembre 2022 1
Modifié le 23 janv. 2020 à 15:50
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
0
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015
Modifié le 24 janv. 2020 à 14:08
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        
0
deep_sea Messages postés 201 Date d'inscription mardi 10 mai 2016 Statut Membre Dernière intervention 10 décembre 2022 1
Modifié le 5 févr. 2020 à 12:04
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;
0
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015
24 févr. 2020 à 11:47
0