Using the Vertx SQL Client API (https://vertx.io/docs/vertx-jdbc-client/java/#_using_the_sql_client_api) how can I execute an update and get the number or rows updated to tell me if the update was a success.
I used LAST_INSERTED_ID for inserts, but what about updates and deletes?
return db.client.preparedQuery(
"DELETE FROM table WHERE id = ?")
.execute(Tuple.of(id))
.map(rs -> rs.property(MySQLClient.?????)
);
Thanks!
The number of affected rows should be given by the SqlResult.rowCount() method:
db.client.preparedQuery("DELETE FROM table WHERE id = ?")
.execute(Tuple.of(id))
.map(res -> {
int count = res.rowCount());
return count;
})
);
Related
The goal of my springBoot webflux r2dbc application is Controller accepts a Request including a list of DB UPDATE or INSERT details, and Response a result summary back.
I can write a ReactiveCrudRepository based repository to implement each DB operation. But I don't know how to write the Service to group the executions of the list of DB operations and compose a result summary response.
I am new to java reactive programing. Thanks for any suggestions and help.
Chen
I get the hint from here: https://www.vinsguru.com/spring-webflux-aggregation/ . Ideas are :
From request to create 3 Monos
Mono<List> monoEndDateSet -- DB Row ids of update operation;
Mono<List> monoCreateList -- DB Row ids of new inserted;
Mono monoRespFilled -- partly fill some known fields;
use Mono.zip aggregate the 3 monos, map and aggregate the Tuple3 to Mono to return.
Below are key part of codes:
public Mono<ChangeSupplyResponse> ChangeSupplies(ChangeSupplyRequest csr){
ChangeSupplyResponse resp = ChangeSupplyResponse.builder().build();
resp.setEventType(csr.getEventType());
resp.setSupplyOperationId(csr.getSupplyOperationId());
resp.setTeamMemberId(csr.getTeamMemberId());
resp.setRequestTimeStamp(csr.getTimestamp());
resp.setProcessStart(OffsetDateTime.now());
resp.setUserId(csr.getUserId());
Mono<List<Long>> monoEndDateSet = getEndDateIdList(csr);
Mono<List<Long>> monoCreateList = getNewSupplyEntityList(csr);
Mono<ChangeSupplyResponse> monoRespFilled = Mono.just(resp);
return Mono.zip(monoRespFilled, monoEndDateSet, monoCreateList).map(this::combine).as(operator::transactional);
}
private ChangeSupplyResponse combine(Tuple3<ChangeSupplyResponse, List<Long>, List<Long>> tuple){
ChangeSupplyResponse resp = tuple.getT1().toBuilder().build();
List<Long> endDateIds = tuple.getT2();
resp.setEndDatedDemandStreamSupplyIds(endDateIds);
List<Long> newIds = tuple.getT3();
resp.setNewCreatedDemandStreamSupplyIds(newIds);
resp.setSuccess(true);
Duration span = Duration.between(resp.getProcessStart(), OffsetDateTime.now());
resp.setProcessDurationMillis(span.toMillis());
return resp;
}
private Mono<List<Long>> getNewSupplyEntityList(ChangeSupplyRequest csr) {
Flux<DemandStreamSupplyEntity> fluxNewCreated = Flux.empty();
for (SrmOperation so : csr.getOperations()) {
if (so.getType() == SrmOperationType.createSupply) {
DemandStreamSupplyEntity e = buildEntity(so, csr);
fluxNewCreated = fluxNewCreated.mergeWith(this.demandStreamSupplyRepository.save(e));
}
}
return fluxNewCreated.map(e -> e.getDemandStreamSupplyId()).collectList();
}
...
All,
I am sending a list of Ids( More than the max of 1000 allowed by Oracle) in the sql where clause using Dapper 1.50 and Oracle 18. Since there is a limit on the number of items in the in clause, I decided to do a sub query as below but I can't get this to working. Can someone shed some light on this. I will always be sending more than 1000 items as Ids. The second sql statement is not working( It says invalid sql).
public static List<Notes> GetNotes()
{
List<Notes> notes = new List<Notes>();
try
{
using (var connection = OracleConnectionString)
{
connection.Open();
string idCommand = #"select * from (select
id
from
note_text
order by
1
desc)where
rownum <=2000";
var notesList = connection.Query<Notes>(idCommand);
var noteIds1 = notesList .Select(i => i.id).ToList();
string command = #"select
tnt.id as id,
tnt.NOTE_TXT
from
note_text tnt
(
select
note_id
from
dual
where
note_id in :noteIds1
)x where x.note_id = tnt.id";
var info = connection.Query<Notes>(command, new
{
noteIds1
});
notes = info.ToList();
}
}
catch (Exception ex)
{
}
return notes;
}
Where does this list of id's originate? I'd get them into a file that can be accessed as an external table. Then, instead of
select ...
from ...
where id in (<listthatstoolong)
you would
select ...
from ...
where id in (select id from id_external_table)
Then you are not limited to a size of a string of elements in your IN list.
I have event table in Corvid Database, it has Event_Id column for every new event which is not asked from the user in the form.
I used the following code to get the number of rows and generate id from that which works good now:
let count = 0;
$w("#collection").onReady( () => {
count = $w("#collection").getTotalCount(); // 23
count++;
} );
$w('#btnSub').onClick( ()=>{
const newRequest = {
eventid:('event_'+count),
title: $w('#title').value
}
wixData.insert('event_instance', newRequest);
but this can lead to duplication of event id as I delete one of the row from collection
Can you please find a solution for this?
Thanks
You need to use dropdowns in #myElementID
This similar to this in SQL.
if not exists (select * from Delegates d where d.FromYr = #FromYr and d.MemNo = #MemNo)
INSERT INTO Delegates ([MemNo],[FromYr],[ToYr]) values(#MemNo, #FromYr,#ToYr)
Else refer this
Make sense get count before each insert
$w('#collection').onReady( () => {
$w('#btnSub').onClick( () => {
const count = $w('#collection').getTotalCount() + 1; // here
wixData.insert('event_instance', {
eventid: ('event_' + count),
title: $w('#title').value
});
});
});
I have the following method inside my asp.net mvc, and i am trying to understand how will entity framework behave when multiple users access the same method :-
public int changeDeviceSwitch(int fromID , int toID)
{
var currentdevices = IT.ITSwitchPorts.Where(a => a.SwitchID == fromID);
int count = 0;
foreach (var d in currentdevices)
{
tms.ITSwitchPorts.Remove(d);
count++;
}
foreach (var d in currentdevices)
{
ITSwitchPort tsp = new ITSwitchPort() { SwitchID = toID, TechnologyID = d.TechnologyID, PortNumber = d.PortNumber };
IT.TMSSwitchPorts.Add(tsp);
}
IT.SaveChanges();
return count;
}
The above method, will mainly, retrieve all the records that have switchID = fromID, then remove all these records and add new records with new switchID.
so my question is what will happen if multiple users access the same method at the same time? as i understand that entity framework can handle the concurrent access in this way as follow:-
-userA call the method
-userB calls the same method
-userA retrieve all the records, delete, then add new records , save.
-userB retrieve all the records , delete, add new records. but when userB reach the saveChnages() ,
entity framework will raise a DbUpdateConcurrencyException when it try to delete a record that no more exists ? so is this what will happen. ?
can anyone advice please?
Thanks
General approach to locking in EF is to use Optimistic locking.
EF Locking docu
SO example
-userB retrieve all the records , delete, add new records. but when userB reach the saveChnages() , entity framework will raise a
DbUpdateConcurrencyException when it try to delete a record that no
more exists ? so is this what will happen. ?
Yes this is what will happen IF you have declared a Concurrency field on the record.
eg
public virtual byte[] RowVersion { get; set; }
I have two JDBC SQL prepared statements in the program to UPDATE tables (different areas of program). When I run the statement, I can see the updates in MySQL when I query the table. So I know the update is happening. However, I have a table connected to the DB in the program that does not show the updated results unless I stop running the program and restart it. Then the updates show in the table. I have other prepared statements that use INSERT INTO and these changes show up right away in the tables (I don't have to stop-restart my program). I don't know if the problem lies in the UPDATE, or in my code (the usual culprit), or some setting I have wrong. I think I might be passing things wrong between method calls. This is part of what it does: I have an income table, the user creates a new income listing, and part of that listing gets sent to a FUNDS table (with the UPDATE statement) and another part gets sent to an INCOME table (with the INSERT INTO statement). Here is the code, thanks for help and suggestions!
//Get user info
Income income = new Income();
Funds fund = new Funds();
income.setIncomeName(jTextField10.getText());
String budgetAmt = jTextField11.getText();
BigDecimal bAmt = new BigDecimal(budgetAmt);
income.setAmount(bAmt);
income.setDescription(jTextArea3.getText());
String iDate = jTextField12.getText();
Date date = new SimpleDateFormat("MM-dd-yy", Locale.ENGLISH).parse(iDate);
java.util.Date utilDate = date;
java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime());
income.setDateReceived(sqlDate);
s = (String)jList10.getSelectedValue().toString();
income.setFundAllocation(s);
// Send info to be processed in FUND table with UPDATE - start of problem area
FundsSvcJDBCImpl fundImpl = new FundsSvcJDBCImpl();
Funds calculateFundAmt = fundImpl.calculateFundAmt(fund, income);
// Send info to be process in INCOME table - this part works
IncomeSvcJDBCImpl budgetImpl = new IncomeSvcJDBCImpl();
Income addIncome = budgetImpl.addIncome(income);
//This is the part of the FundsSvcJDBCImpl that uses the UPDATE statement
public Funds calculateFundAmt (Funds fund, Income income) throws Exception {
Statement stmt = null;
int max = 0;
BigDecimal fundTotal = new BigDecimal(0);
Connection conn = getConnection();
try{
stmt = conn.createStatement();
String sql1 = "SELECT sum(Amount) As fundTotal FROM funds WHERE FundsName = ?";
PreparedStatement pstmt1 = conn.prepareStatement(sql1);
pstmt1.setString(1, income.getFundAllocation());
ResultSet rs2 = pstmt1.executeQuery();
while(rs2.next()){
fundTotal = fundTotal.add(rs2.getBigDecimal("fundTotal"));
}
fundTotal = fundTotal.add(income.getAmount());
String sql2 = "UPDATE funds SET Amount = ? WHERE FundsName = ?";
PreparedStatement pstmt = conn.prepareStatement(sql2);
pstmt.setBigDecimal(1, fundTotal);
pstmt.setString(2, income.getFundAllocation());
pstmt.executeUpdate();
}
catch (Exception e){
throw e;
}
finally {
if (conn != null){
conn.close();
stmt.close();
}
}
return fund;
}