Potřebuji poradit s jednou pro vás nejspíš triviální věcí.

Snažím se naučit, jak se pracuje s persistencí a s JPA ale stále v tom tápu, bo 
angličtina není zrovna moje hobby a nejspíš hodně občas nedokážu anglické 
manuály správně přeložit.

Používám NetBeans .
Mám desktop aplikaci, s databází MySQL a JDBC balíček, toplink a
org.jdesktop.beansbinding (ty jsou dodané v NetBeans).

Mám dvě tabulky

CREATE TABLE `klienti` (
  `klic` int(11) NOT NULL auto_increment,
  `pr_naz` varchar(50) ,

  ...

  PRIMARY KEY  (`klic`),
  KEY `pr_naz` (`pr_naz`),
  KEY `typ` USING BTREE (`typkl`)
)

CREATE TABLE `adresar` (
  `klic` int(11) NOT NULL auto_increment,
  `klienti_klic` int(11) NOT NULL default '0',
  `jm` varchar(18) ,
  `pr_naz` varchar(50) ,
  ...
  ulice,telefony atd ...
  ....

  PRIMARY KEY  (`klic`),
  KEY `pr_naz` (`pr_naz`),
  KEY `klienti_klic` USING BTREE (`klienti_klic`),
  CONSTRAINT `FK_adresar_klienti` FOREIGN KEY (`klienti_klic`) REFERENCES 
`klienti` (`klic`)
  )

Relace je klienti:adresar je  1:n

NetBeans mi podle cizího klíče vygeneroval entity:

@Entity
@Table(name = "klienti")
@NamedQueries(
{
    @NamedQuery(name = "Klienti.findByKlic", query = "SELECT k FROM Klienti k 
WHERE k.klic = :klic"),
    @NamedQuery(name = "Klienti.findByPrNaz", query = "SELECT k FROM Klienti k 
WHERE k.prNaz = :prNaz"),

    ...
})
public class Klienti implements Serializable {

    @Id
    @Column(name = "klic",updatable=false, nullable = false)
    private Long klic;
    @Column(name = "pr_naz", nullable = false)
    private String prNaz;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "klienti")
    @JoinColumn(name="klienti_klic")
    private Collection<Adresar> adresarCollection;

    public Klienti() {  }


    public Long getKlic() {  return klic;    }
    public void setKlic(Long klic)    {  this.klic = klic; }
    public String getPrNaz()    {   return prNaz;  }
    public void setPrNaz(String prNaz)    {   this.prNaz = prNaz;   }


    public Collection<Adresar> getAdresarCollection()  {   return 
adresarCollection;  }

    public void setAdresarCollection(Collection<Adresar> adresarCollection)  {
       this.adresarCollection = adresarCollection;
    }

    public void addAdresar(Adresar adr)   {
        adr.setKlienti(this);
        this.adresarCollection.add(adr);
    }

    public Adresar newAdresar() {
        Adresar adresar;
        adresar = new Adresar();
        entityManager.persist(adresar);
        addAdresar(adresar);
        return adresar;
    }

    @Override
    public int hashCode() ....

    @Override
    public boolean equals(Object object) ...

    @Override
    public String toString() ...

}

@Entity
@Table(name = "adresar")
@NamedQueries(
{
    @NamedQuery(name = "Adresar.findByKlic", query = "SELECT a FROM Adresar a 
WHERE a.klic = :klic"),
    @NamedQuery(name = "Adresar.findByPrNaz", query = "SELECT a FROM Adresar a 
WHERE a.prNaz = :prNaz"),

    ...

})
public class Adresar implements Serializable, InterfaceAdresar
{

    @Id
    @Column(name = "klic", nullable = false)
    private Integer klic;
    @Column(name = "pr_naz", nullable = true)
    private String prNaz;

    @JoinColumn(name = "klienti_klic", referencedColumnName = "klic")
    @ManyToOne
    private Klienti klienti;


    public Adresar()
    {
    }

    public Integer getKlic()  {  return klic; }
    public void setKlic(Integer klic) { this.klic = klic; }


    public String getPrNaz()  { return prNaz;  }
    public void setPrNaz(String prNaz)   {  this.prNaz = prNaz;    }

    @Override
    public int hashCode() { ... }

    @Override
    public boolean equals(Object object)  { ... }

    @Override
    public String toString() { ... }


    public Klienti getKlienti()
    {  return klienti;    }

    public void setKlienti(Klienti klienti)
    {    Klienti oldKlienti = this.klienti;
        this.klienti = klienti;
        changeSupport.firePropertyChange("klienti", oldKlienti, klienti);
    }


}

používám systém tak jak to vygeneruje NetBeans s tím,
že se transakce otevře v konstruktoru formuláře
 entityManager.getTransaction().begin();

nový klient do formuláře se získá:

        cz.ahsw.klienti.entity.Klienti kli = new 
cz.ahsw.klienti.entity.Klienti();
        entityManager.persist(k);

a pro novou adresu k němu se využije metoda Adresar.newAdresar()
tj.

            Adresar adr = kli.newAdresar();


Uloží se
    private void saveButtonActionPerformed(java.awt.event.ActionEvent evt) {

        entityManager.getTransaction().commit();
        entityManager.getTransaction().begin();
    }


Update funguje
Přidávat nové adresy ke klientovi, který je již v předešlém kroku uložen
v databázi jde též bez chyby.

Ovšem při pokusu založit klienta i jeho adresu zároveň nelze.
Nepřenese se do adresy klíč klienta a insert zkončí na tom,
že databáze zabrání vložení null hodnoty.


Call: INSERT INTO adresar (klic, tel, mobil_fax, pr_naz, email, cp, ins_kdy, 
jm, ins_kdo, mesto, uli, klienti_klic) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 
?)
        bind => [null, null, null, null, null, null, null, null, 0, iojuoiuoi, 
kljkljl, null]
Query: 
InsertObjectQuery(cz.ahsw.klienti.entity.Adresar[klic=null];null,null,kljkljl,null,null)
Exception in thread "AWT-EventQueue-0" javax.persistence.RollbackException: 
Exception [TOPLINK-4002] (Oracle TopLink Essentials - 2.0 (Build b58g-fcs 
(09/07/2007))): oracle.toplink.essentials.exceptions.DatabaseException
Internal Exception: 
com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException: Column 
'klienti_klic' cannot be null
Error Code: 1048


Kde je problém, že se ten nový klíč nepřenese do instance adresar, kterou má v 
kontejneru
a měl by je též insertovat?

Může mi s tím někdo poradit?

Může mě někdo orientovat na nějaký dobře napsaný a pochopitelný tutoriál, 
nejlépe v češtině?
Jsem s JPA naprosto na začátku. Trošku mě zklamal. Jsem zvyklý psát v SQL (ISO) 
– je to trochu víc práce, ale funguje to jak předpokládám.
Tyhle persistence jsou černá skřínka a co z toho vyleze zatím netuším. Zatím mi 
studium a hledání informací po internetu zabralo příliš mnoho času a netuším, 
zda se efektivita zvedne oproti míře vynaloženého úsilí natolik, aby se mi to 
vyplatilo to toho JPA jít…

Díky mnohokrát za rady :-)!

Arnošt

Odpovedet emailem