PDA

Prikaži potpunu verziju : Java - Iz Vektora u bazu podataka


mcdhappy80
9.5.2010, 17:39
Da li je moguć sledeći scenario:
U formi za unos korisnika unese se nekoliko korisnika odjednom. Svaki od unetih korisnika je instanca klase Osoba npr., a svaka instanca smešta se u jedan Vektor kontejner imena Osobe.
Uspeo sam da napravim da se nakon unosa jedne osobe ista upiše u bazu.
Kako napraviti da nakon unosa nekoliko osoba (koje se zapamte u vektoru) iste budu zapisane u bazu u jednom koraku, sve odjednom?
Pretpostavljam da može (za šta bi inače služile transakcije kao pojam u bazama podataka).
Hvala

irreal
9.5.2010, 20:20
transakcije nemaju nikakve veze sa unosenjem listi (vektora) odjedanput.
niti mozes vektor direktno da upises u bazu, vec napravis petlju koja ce za svaku instancu u vektoru izvrsiti po jedan sql, upisati po jedan red u bazu.

ono sto tebi treba je da se ne izvrsi commit nakon ubacivanja jednog reda, vec da sam pozoves commit komandu kada uneses ceo vektor (iz vise sql naredbi, naravno)

da se podsetimo (svi):
transakcije sluze pre svega da osiguraju pravilan rad baze.

transakcije su kao male procedurice koje rade nesto na bazi, koje ako se prekinu na pola mogu da korumpiraju podatke ili dovedu do nejasnoca.

uz pomoc transakcija sve promene koje radis se pamte sa strane, i tek kada ih commitujes, gaze stare podatke / dodaju nove.

na taj nacin ako u sred nekog posla pukne server koji drzi bazu (ili dodje do druge greske) jedan "posao" je ili zavrsen ili nije ni zapoceo, ne moze da ostane negde na pola (tipa nalog na kome je pola stavki popunjeno a pola nije)

takodje pomaze i kada vise ljudi radi u isto vreme na bazi. ne moze jedan klijent da uhvati neki nalog koji je kreiran ali jos uvek nije napunjen do kraja. ili ne postoji ili je vec zavrsen, i ako je 15 razlicitih sql naredbi kreiralo nalog, npr.

-edit-
a da, sad kapiram da ti nisam napisao nista konkretno kako da izvedes to sto ti treba.
to je zato sto to uglavnom zavisi od drajvera ka bazi i nacina kako ga koristis u javi.
moraces da das mnogo vise informacija kako i na koju bazu se kacis da bi mogli tacno da vidimo kako se radi sa transakcijama.
(negde je samo u pitanju gasenje auto commit-a, negde je nesto komplikovanije)

mcdhappy80
10.5.2010, 13:32
Koristim NetBeans IDE, a povezivao sam se na MySQL bazu.
Interesuje me kako bi izgledao kod Klase koja bi vršila čitanje novoupisanih objekata u vektor i upisivanje istih u bazu. Ovo ostalo imam (povezivanje).
Hvala

irreal
10.5.2010, 13:55
ako umes da upises jednu instancu u bazu, upisivanje vektora je samo petlja uz pomoc koje pristupas svim clanovima vektora i upisujes ih na identicni nacin kao i taj jedan.

ne koristim javu, jos manje znam kako se iz nje kacis na mysql, ali proveri da li tamo gde ti stoje klase connection i command imas i neku klasu transaction.

najverovatnije imas klasu transaction, ciju napravis instancu, a onda sql komandu povezes sa tom transakcijom.

tipa:

Command cmd = new Command();
cmd.Connection = conn;
Transaction trs = new Transaction();
cmd.Transaction = trs;
FOR petlja kojom prolazis kroz vektor
{
cmd.CommandText = "insert bla into truc";
cmd.ExecuteNonQuery();
}
//i sada ovde commitujes transakciju, da bi sve to sto si radio imalo nekog smisla.
trs.Commit();

//a mozes i .RollBack(); ako hoces da odustanes

tako je barem u OleDb.

~Raf~
11.5.2010, 9:29
Mozda nesto ovako:


public class DBBroker {

Connection connection;
Statement statement;

public boolean otvoriKonekciju(){
try{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
connection = DriverManager.getConnection("jdbc:odbc:mojaBaza"); //mojaBaza je naziv tvoje mysql baze
connection.setAutoCommit(false);
} catch(Exception e) {
e.printStackTrace();
return false;
}
return true;
}

public boolean commitAkcije(){
try {
connection.commit();
} catch(Exception e) {
e.printStackTrace();
return false;
}
return true;
}

public boolean zatvoriKonekciju(){
try {
connection.close();
} catch(Exception e) {
e.printStackTrace();
return false;
}
return true;
}

public boolean snimiRed(OpstaDomenskaKlasa odk){
try{
String upit = "INSERT INTO "+ odk.vratiNazivTabele()+ " ("+ odk.vratiNaziveKolonaTabele() +") "+ "VALUES ("+odk.vratiVrednostiAtributa()+")";
statement = connection.createStatement();
//statement.executeUpdate(upit);
statement.close();
} catch(Exception e) {
System.out.println("Nije uspesno zapamcen slog u bazi: " + e);
e.printStackTrace();
return false;
}
return true;
}
}

public interface OpstaDomenskaKlasa extends Serializable{

public String vratiNazivTabele();

public String vratiNaziveKolonaTabele();

public String vratiVrednostiAtributa();

}
Mozes i bez opstedomenskeklase. Ako je koristis onda samo napravis klasu koja ce je naslediti i koja ce predstavljati tabelu u tvojoj bazi podataka. Takodje, mogu i sve metode da budu void ako ti nije bitna provera da li je metoda uspesno zavrsena.

u programu zoves: otvoriKonekciju + snimiRed + commitAkcije + zatvoriKonekciju

Ovo sam iscupao na brzinu iz starog projekat pa je moguce da sam nesto zaboravio...

irreal
11.5.2010, 12:17
eto, dakle u tom slucaju je sve stvar gasenja autocommita, kao sto sam i teoretisao :)

u svakom slucaju samo zelim da dodam da prosledjivanje parametra sql upitu konkatenacijom stringova nije najbolja praksa.
gledaj da za parametre koristis u tu svrhu predvidjene klase.

mcdhappy80
30.7.2010, 17:25
Hvala na prethodnim odgovorima.

Čitao sam da nije praktično otvarati konekciju sa bazom svaki put kada želimo da upišemo jedan red u tabeli baze. Umesto ovoga (ako sam dobro razumeo) konekcija se otvara samo jednom gde se podaci iz baze učitaju u neku Kolekciju (Vektor, ArrayList i sl.) i onda se manipuliše time.

E sada meni se ovde javilo jedno pitanje:

Ako učitamo podatke iz jedne tabele u Vektor, zatim tom vektoru dodamo nove podatke (objekte), i na kraju rada bi ponovo iz tog vektora trebali da isčitamo samo nove podatke koji se ne nalaze u bazi i u bazu upišemo samo njih.

Na koji način se ova funkcionalnost implementira?

Hvala

~Raf~
30.7.2010, 18:28
Ne znam za neki mehanizam koji to radi ali mozes vestacki da zaobidjes problem na razne nacine, npr:
1) imas jedan vektor za podatke iz tabele i drugi koji cuva podatke koje treba uneti, znaci 2 vektora
2) dodas neku int promenljivu N koji pamti broj elemenata u vektoru kad je napunjen podacima iz tabele, posle kada zelis da unosis u tabelu samo proveris da li je povecana velicina vektora na M i ako jeste uneses zadnjih M-N elemenata iz vektora

ovo mi je prvo palo na pamet, mozda neko zna lepse resenje.

irreal
30.7.2010, 19:01
Ne znam za neki mehanizam koji to radi ali mozes vestacki da zaobidjes problem na razne nacine, npr:
1) imas jedan vektor za podatke iz tabele i drugi koji cuva podatke koje treba uneti, znaci 2 vektora
2) dodas neku int promenljivu N koji pamti broj elemenata u vektoru kad je napunjen podacima iz tabele, posle kada zelis da unosis u tabelu samo proveris da li je povecana velicina vektora na M i ako jeste uneses zadnjih M-N elemenata iz vektora

ovo mi je prvo palo na pamet, mozda neko zna lepse resenje.

to ti pokriva dodavanje, a brisanje i izmena ?


u principu, java sigurno ima neku vrstu "data adaptera". ne znam kako bi tacno islo u javi, ali u C# imas data adapter koji pamti sve promene u tabeli koje radis u svom kodu i onda ih primeni na tabelu u bazi (update, insert, delete)

drugo resenje je da radis direktno na bazi (mozes u principu i da drzis otvorenu koneckiju, nista ne ce da fali, ne moras stalno da otvaras pa zatvaras)
i tu bi definitivno koristio transakcije, pa tek kada se sve potrvrdi i proveri, commitujes, da ne bi korumpirao podatke.

treci nacin je, ma da ga ne bi preporucio, da kada potvrdis, obrises celu tabelu u bazi a onda je celu opet upises iz aplikacije.


naravno, najbolje bi ti bilo prvo resenje.

mcdhappy80
31.7.2010, 3:57
to ti pokriva dodavanje, a brisanje i izmena ?


u principu, java sigurno ima neku vrstu "data adaptera". ne znam kako bi tacno islo u javi, ali u C# imas data adapter koji pamti sve promene u tabeli koje radis u svom kodu i onda ih primeni na tabelu u bazi (update, insert, delete)

Jel bi mogao da mi das taj fragment C# koda? Kada vidim mehanizam lako cu naci slicne u Javi.
Ovo OO programiranje je toliko intuitivno da mi vise nije bitno koji je programski jezik u pitanju vec samo koncept, koji se opet u zavisnosti od jezika, slicno implementira.

Hvala

irreal
31.7.2010, 12:14
ma nema nista lakse od koda kojim se KORISTI DataAdapter, ali to ti nece pokazati kako je isti u pozadini implementiran.

http://dotnetperls.com/sqldataadapter-adonet

no, ne moramo ni da ulazimo u diskusiju o tome kako je implementiran (o cemu mozes citati na gomili mesta, recimo wikipediji), kada i java sigurno ima vise nego adekvatne klase (dal originalno, dal u vidu besplatnih paketa) tako da samo treba malo da se druzis sa guglom i to je to.

Yellua
11.8.2010, 12:55
ono sto tebi treba je da se ne izvrsi commit nakon ubacivanja jednog reda, vec da sam pozoves commit komandu kada uneses ceo vektor (iz vise sql naredbi, naravno)


Upravo to bi bila transakcija.. Dakle niz operacija koje se izvrse pre pozivanja commit komande bi bila jedna transakcija. Ukoliko se medju tim operacijama pojavi greska, izvrsi se rollback i baza se vrati u prvobitno stanje.. Tako da transakcije i te kako imaju veze sa ovim, a ne kao sto si ti napisao... ;)

@mcdhappy80
za poslednje postavljeno pitanje, ja bih kao sto Raf kaze, iskoristila dva vektora..

irreal
11.8.2010, 14:32
Upravo to bi bila transakcija.. Dakle niz operacija koje se izvrse pre pozivanja commit komande bi bila jedna transakcija. Ukoliko se medju tim operacijama pojavi greska, izvrsi se rollback i baza se vrati u prvobitno stanje.. Tako da transakcije i te kako imaju veze sa ovim, a ne kao sto si ti napisao... ;)

@mcdhappy80
za poslednje postavljeno pitanje, ja bih kao sto Raf kaze, iskoristila dva vektora..

pa aj procitaj ceo moj post, a zatim i onaj sledeci gde objasnjavam kako se koristi transakcija za upisivanje vektora u bazu, 'leba ti.

ja sam pokusao da objasnim da transakcija nije nesto sto automatski upisuje vektor u bazu, ali nikada nisam rekao da ne treba da se koristi prilikom upisivanja, ili jos gore da NE MOZE da se koristi tokom upisivanja.
naprotiv, demonstrirao sam kako moze i kako teoretski treba.

dakle, da, transakcije imaju veze sa ovim, jer nije losa ideja koristiti ih, ali ti vektor i dalje upisujes izvrsavanjem normalnih sql query-ja. samo koristis transakciju da sve te query-je potvrdis odjedanput.

transakcija je nesto sto ti pomaze da se zastitis od pucanja operacije u sred upisivanja i gubitka ili korumpiranja podataka, ali nije nesto sto moras da koristis da bi upisao vektor u bazu.

sve sam to vrlo jasno i lepo napisao jos u maju, pa ne vidim cemu pokretanje toga ponovo u avgustu, kad ne rece nista novo.

Yellua
11.8.2010, 16:42
transakcije nemaju nikakve veze sa unosenjem listi (vektora) odjedanput.
...
ono sto tebi treba je da se ne izvrsi commit nakon ubacivanja jednog reda, vec da sam pozoves commit komandu kada uneses ceo vektor (iz vise sql naredbi, naravno)

Iz ovoga sam stekla utisak da si o ovome pricao kao da su to dve razlicite stvari. Ako nisi to mislio, moja greska. A vidim, moja greska je sto sam uopste bilo sta pisala. Nece se ponoviti.

irreal
11.8.2010, 16:57
nije greska sto si bilo sta pisala, zasto bi bila.
samo sam mislio da je ocigledno sta sam napisao, a izgleda da nije bilo.

da, i dalje tvrdim da transakcije nemaju DIREKTNO veze sa upisom vektora u bazu.

jer sve i ako se radi commit nakon svakog upita u prolazu kroz for petlju, vektor ce i dalje biti upisan u bazu, i to je i dalje validan (ali ne siguran) nacin za upis vektora.

a transakcija tu samo sluzi kao osiguranje.


a drugi deo citata je slikovito objasnjavao u kom svojstvu treba da iskoristi transakciju. ne kao nesto sto upisuje vektor, vec nesto sto omogucava osiguranje protiv pucanja u sred upisa.


u svakom slucaju, nesporazum resen, nadam se.