2010-07-19 17 views
1

je utilise:clés primaires commencent Generated forme 9951 au lieu de 10000

NetBeans IDE 6.7.1, GlassFish v2.1, Oracle 10g XE, JAVA SE 6, JAVA EE 5,

de l'intérieur d'un EJB sans état je persiste des entités de type client je l'annotation: @SequenceGenerator (name = « seq », nom de séquence = « cust_id_seq ») dans le client de classe pour les clés primaires sont générées automatiquement dans la base de données la séquence cust_id_seq mais quand je persiste le premier client la clé primaire est 9951 au lieu de 1000 0, la clé primaire du deuxième client est 9952. La sortie du GlassFish v2.1 après avoir persisté deux clients est:

Le démarrage du serveur d'applications est terminé.

Mon id est: 0

TopLink, version: Oracle TopLink Essentials - 2.1 (Build-b31g SVF (10/19/2009))

serveur: fichier inconnu:/C:/Documents % 20et% 20Settings/IOANNIS_PAPAIOANNOU/Mon% 20Documents/NetBeansProjects/VideoClub/dist/gfdeploy/VideoClub-ejb_jar/-vc_pu connexion réussie

Mon id est: 9951

Mon id est: 0

Mon id est: 9952

@Entity 
@Table(name = "customer") 
@SequenceGenerator(name="seq", sequenceName="cust_id_seq") 
public class Customer implements Serializable 
{ 

@Id 
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="seq") 
@Column(name="CUST_ID") 
private int id; 

@Column(name = "phone_number") 
private int phoneNumber; 

@Column(name = "first_name") 
private String firstName; 

@Column(name = "last_name") 
private String lastName; 

@Column(name = "credit") 
private int credit; 

@OneToMany  
private Collection<CustRentMovie> rents = new ArrayList<CustRentMovie>(); 

public int getCredit() 
{ 
    return credit; 
} 

public void setCredit(int credit) 
{ 
    this.credit = credit; 
} 

public String getFirstName() 
{ 
    return firstName; 
} 

public void setFirstName(String firstName) 
{ 
    this.firstName = firstName; 
} 

public int getId() 
{ 
    return id; 
} 

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

public String getLastName() 
{ 
    return lastName; 
} 

public void setLastName(String lastName) 
{ 
    this.lastName = lastName; 
} 

public int getPhoneNumber() 
{ 
    return phoneNumber; 
} 

public void setPhoneNumber(int phoneNumber) 
{ 
    this.phoneNumber = phoneNumber; 
} 

public Collection<CustRentMovie> getRents() 
{ 
    return rents; 
} 

public void setRents(Collection<CustRentMovie> rents) 
{ 
    this.rents = rents; 
} 


} 

le code de l'EJB:

@Stateless 
public class ClerkSessionBean implements ClerkSessionRemote 
{ 

@PersistenceContext(unitName = "vc_pu") 
private EntityManager em; 

public int writeCustomer(AlmostCustomer almostCustomer) 
{ 

    Customer customer = new Customer(); 
    System.out.println("My id is: " + customer.getId()); 
    customer.setFirstName(almostCustomer.getFirstName()); 
    customer.setLastName(almostCustomer.getLastName()); 
    customer.setPhoneNumber(almostCustomer.getPhoneNumber()); 
    em.persist(customer); 
    System.out.println("My id is: " + customer.getId()); 
    return customer.getId(); 
} 
} 

partie du script qui crée la base de données:

CREATE table customer 
(
cust_id NUMBER(5), 
phone_number NUMBER(10) NOT NULL, 
first_name VARCHAR2(12) NOT NULL, 
last_name VARCHAR2(30) NOT NULL, 
-- Τα χρήματα που έχει ένας πελάτης στο λογαριασμό του. 
credit NUMBER(5, 2) DEFAULT 0 NOT NULL, 
CONSTRAINT cust_pk PRIMARY KEY (cust_id), 
-- Μόνο ένας λογαριασμός για κάθε σπίτι. 
CONSTRAINT phone_unique UNIQUE (phone_number) 
) 
/

DROP SEQUENCE cust_id_seq 
/

CREATE SEQUENCE cust_id_seq MINVALUE 10000 MAXVALUE 99999 INCREMENT BY 1 START WITH 10000 NOCACHE NOCYCLE ORDER 

/

Yiannis P

Répondre

0

Dans l'entité client dans le @SequenceGenerator d'annotation j'ai ajouté le atribute allocationSize avec la valeur 1, maintenant les clés primaires commencent à partir 10000.

@Entity 
@Table(name = "customer") 
@SequenceGenerator(name="seq", sequenceName="cust_id_seq", allocationSize=1) 
public class Customer implements Serializable 
{ 

    @Id 
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="seq") 
    @Column(name="CUST_ID") 
    private int id; 
... 
} 
3

Je pense que vous devriez changer CREATE SEQUENCE cust_id_seq ... INCREMENT BY1 à ... INCREMENT BY50. Voici pourquoi. L'incrément de séquence déclaré doit correspondre au paramètre allocationSize de @SequenceGenerator. n'est pas spécifié et par défaut vaut 50. Mais le vrai INCREMENT BY est seulement 1, pas 50. Donc, il y a une discordance entre allocationSize et le vrai INCREMENT BY.

Voici comment cette discordance pourrait causer le problème. TopLink Essentials (TLE) appelle NEXTVAL() sur cust_id_seq. La séquence renvoie 10000 + 1. TLE suppose que la séquence vient d'être incrémentée de 50 (par défaut JPA allocationSize) au lieu de 1 (quantité réelle). TLE = 50 allocationSize retranche de 10001 pour obtenir 9951.

Par ailleurs, si vous avez la liberté de le faire, pensez à la mise à niveau au successeur de TLE, EclipseLink (et Glassfish v3).

+0

+1 Vous avez raison sur toute la ligne. 1) Oui, le 'allocationSize' du générateur de séquence doit correspondre à la valeur d'incrément de la séquence dans la base de données. 2) Oui, c'est comme ça que l'algorithme fonctionne du côté TLE. 3) Oui, la valeur par défaut allocationSize est 50 avec JPA 1.0 aussi. –

+0

@Pascal Thivent - merci pour votre expertise! –

+0

Je suis en vacances en ce moment je vais essayer votre solution la semaine prochaine. – IVANNHS