How to change this statement to detached criteria - sql

This statement is to check if the user is existing in the database.
public boolean isExisting(int userId) {
String sql = "{call isExistingUser(?)}";
Session session = null;
boolean isExisting = false;
try {
session = getSession();
SQLQuery query = session.createSQLQuery(sql);
query.setParameter(0, userId);
List<?> list = query.list();
isExisting = list.get(0) != null ? (Boolean) list.get(0) : false;
} finally {
if (session != null)
session.close();
}
return isExisting;
}
This is the stored procedure:
CREATE DEFINER=cbsadmin#% PROCEDURE isExistingUser(IN userId int)
BEGIN
SELECT USER_ID FROM USER_LOGIN_STATUS WHERE USER_ID = userId;
END

It is not possible to query a Stored procedure using detached criteria in NHibernate.
You need to use SQL query only.
See here.

Related

Dapper for NET Core: Insert into a table and return id of inserted row [duplicate]

This question already has answers here:
How do I perform an insert and return inserted identity with Dapper?
(9 answers)
Closed 6 months ago.
I have the following method in my repository. As of now, i believe the int returned is simply one indicating whether or not the operation was successful. I want the int to be the id (which is the single column of the table) to be returned after a successful execution. How do i accomplish this?
public async Task<int> AddNewGroup()
{
using(_connection)
{
_connection.Open();
var id = await _connection.ExecuteAsync("INSERT INTO groups").Single();
}
}
You can run a query which has 2 parts, first is your INSERT part and second is a SELECT part. In the SELECT part, you can return(select) whatever column value you want.
For example, If your group table has a primary key column called GroupId and you have set that column for Identity value generation(automatic value generation), you can call the SCOPE_IDENTITY() to get the generated value.
We will use the QueryAsync method.
public async Task<int> AddNewGroup()
{
using(_connection)
{
_connection.Open();
var q = #"INSERT INTO Groups(Name,Description) VALUES
(#name, #desc); SELECT CAST(SCOPE_IDENTITY() as int)"
var result = await _connection.QueryAsync<int>(q,
new { #name="some name", #desc="some desc"});
return result.Single();
}
}
You don't have to create by hand the insert query, you can use Dapper.Contrib github which helps you to manage CRUD operations.
Using Dapper.Contrib you can do something like:
public async Task<int> AddNewGroup(Group entity)
{
using (_connection)
{
_connection.Open();
var id = await _connection.InsertAsync(entity);
}
}
If you're using SQL Azure / SQL Server, you need to return the inserted value from the query using something like
INSERT INTO groups OUTPUT inserted.id VALUES (...)
and then instead using ExecuteAsync use ExecuteScalarAsync
Reference to the OUTPUT clause here:
https://learn.microsoft.com/en-us/sql/t-sql/queries/output-clause-transact-sql?view=sql-server-2017
public static void Main()
{
string sql = #"INSERT INTO Customers (CustomerName, ContactName, Address, City, PostalCode, Country)
Values (#CustomerName, #ContactName, #Address, #City, #PostalCode, #Country);
SELECT CustomerID FROM Customers WHERE CustomerID = SCOPE_IDENTITY();";
using (var connection = new SqlConnection(GetConnectionString()))
{
Customer c = new Customer("Brian Adams", "Brian", "12 Jones Place", "New York", "NY12", "CA");
var id = connection.QueryFirstOrDefault<int>(sql, c);
Console.WriteLine("The Customer ID is " + id);
sql = "Select * FROM CUSTOMERS WHERE CustomerID = #ID";
var rc = connection.QueryFirstOrDefault<Customer>(sql, new{ #ID = id });
}
}
}
The "correct" way that I took is (Showing repository method using Guid Id to return):
public async Task<Guid> CreateClient(ClientEntity clientModel)
{
const string sql = #"
INSERT INTO dbo.Clients
(
ClientCode,
Name,
IsActive
)
OUTPUT Inserted.ClientId
VALUES
(
#ClientCode,
#Name,
#IsActive
)";
using var dbConnection = await _databaseProvider.GetConnection();
var result = await dbConnection.ExecuteScalarAsync(sql, new
{
ClientCode = clientModel.Code,
Name = clientModel.Name,
IsActive = clientModel.IsActive
});
if (result != null)
{
return Guid.Parse(result.ToString());
}
else {
return Guid.Empty;
}
}
You can use the RETURNING id in the insert statement. This is using C# and dapper.
private readonly NpgsqlConnection _connection = new NpgsqlConnection();
var sqlInsert = $""""
INSERT INTO tabel_name (column_name)
VALUES ('value')
RETURNING id;
"""";
var id = await _connection.ExecuteScalarAsync(sqlInsert);
And if you want to determine the key type coming back you can use:
var id = await _connection.ExecuteScalarAsync<int>(sqlInsert);
Where you specify the type in the <> brackets. If you do not specify, it will return the object type.

NHibernate named query and multiple result sets

We have a stored procedure that returns several tables. When calling it using NHibernate, we use the bean transformer but only get the first table transformed and all other results are ignored.
I know that NH is able to process several queries in one db trip using futures but we only have one query and it produces a result that is similar to what we would get with futures, but getting this from a stored procedure.
I believe this scenario is quite common but could not find any clues. Is it possible to use NH to retrieve such results?
Yes,you can use MultiQuery "Hack" like this:
The procudure:
CREATE PROCEDURE [dbo].[proc_Name]
AS BEGIN
SELECT * FROM Question
SELECT * FROM Question
END
The NHibernate Query Code:
public void ProcdureMultiTableQuery()
{
var session = Session;
var procSQLQuery = session.CreateSQLQuery("exec [proc_Name] ?,?");// prcodure returns two table
procSQLQuery.SetParameter(0, userId);
procSQLQuery.SetParameter(1, page);
procSQLQuery.AddEntity(typeof(Question));
var multiResults = session.CreateMultiQuery()
.Add(procSQLQuery)
// More table your procedure returns,more empty SQL query you should add
.Add(session.CreateSQLQuery(" ").AddEntity(typeof(Question))) // the second table returns Question Model
.List();
if (multiResults == null || multiResults.Count == 0)
{
return;
}
if (multiResults.Count != 2)
{
return;
}
var questions1 = ConvertObjectsToArray<Question>((System.Collections.IList)multiResults[0]);
var questions2 = ConvertObjectsToArray<Question>((System.Collections.IList)multiResults[1]);
}
static T[] ConvertObjectsToArray<T>(System.Collections.IList objects)
{
if (objects == null || objects.Count == 0)
{
return null;
}
var array = new T[objects.Count];
for (int i = 0; i < array.Length; i++)
{
array[i] = (T)objects[i];
}
return array;
}

How to query database and return single row only

I'm new to programming and I'm trying to do simple projects to learn more. I've done researching, but I can't seem to find a solution to my problem. Perhaps, my program is not properly structured, but here it goes:
THIS BLOCK WILL VALIDATE IF THE ENTERED EMPLOYEE ID ALREADY EXISTS IN DATABASE. THIS IS CALLED IN A SERVLET
public boolean login(String employeeID) throws SQLException {
String sql = "select count(*) as count from employees where emp_id=?";
statement = connection.prepareStatement(sql);
statement.setString(1, employeeID);
rs = statement.executeQuery();
if (rs.next()) {
count = rs.getInt("count");
}
rs.close();
if (count == 0) {
return false;
} else {
return true;
}
}
/* METHOD BELOW ITERATES THE FIELDS FROM MYSQL DATABASE, BUT IT DISPLAYS ALL OF IT.
I JUST WANT TO GET A SINGLE ROW MATCHING THE EMPLOYEE ID PARAMETER ENTERED.*/
public List<EmployeeNumber> _list() throws SQLException {
List<EmployeeNumber> result = new ArrayList<>();
String sql = "select * from employees";
statement = connection.prepareStatement(sql);
rs = statement.executeQuery();
if (rs.next()) {
EmployeeNumber emp = new EmployeeNumber();
emp.setEmployeeNumber(rs.getString(1));
emp.setFirstName(rs.getString(2));
emp.setLastName(rs.getString(3));
emp.setEmail(rs.getString(4));
emp.setDepartment(rs.getString(5));
emp.setFirstApprover(rs.getString(6));
emp.setSecondApprover(rs.getString(7));
result.add(emp);
}
if (rs != null) {
rs.close();
}
if (statement != null) {
statement.close();
}
if (connection != null) {
connection.close();
}
return result;
}
}
I think it has something to do with my SQL Query statement but I can't figure out how to fix it.
So in a nutshell, when I submit the employee ID from JSP page, it will validate if that exists, and if it does, I want to display all the column fields within the same row where this employee ID is positioned. How do I do that? Results will be displayed on another JSP page.
Thank you.
You're first counting how many employees have the given ID. Then you're selecting all the rows from the employee table.
Skip the first query, and only use the second one, but by adding a where clause, just as you did with the first query:
select * from employees where emp_id=?
Then after you've bound the parameter (as you did for the first query), test if there is a row returned:
if (rs.next()) {
// get the data, and return an EmployeeNumber instance containing the data
}
else {
// no employee with the given ID exists: return null
}
Note that the method shouldn't return a List<EmployeeNumber>, but an EmployeeNumber, since you only want to get 1 employee from the table.
Maybe try something like this?
String sql = "select count(*) as count from employees where emp_id=?";
statement = connection.prepareStatement(sql);
statement.setString(1, employeeID);
int count = statement.ExecuteScalar();
if (count == 0) {
return false;
} else {
return true;
}
}
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.executescalar(v=vs.110).aspx
You can also set a breakpoint and step through your code and see where the exception is being thrown. That would help us, knowing the exception message and where it's breaking.

Existing posts keep on re-add upon deletion of selected row in jTable

I try to refresh the data of jTable upon deletion of selected row. Here are my codes to set up table :
private JTable getJTableManageReplies() {
jTableManageReplies.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
jTableManageReplies.getSelectionModel().addListSelectionListener(
new ListSelectionListener() {
#Override
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
int viewRow = jTableManageReplies.getSelectedRow();
// Get the first column data of the selectedrow
int replyID = Integer.parseInt(jTableManageReplies.getValueAt(
viewRow, 0).toString());
eForumRepliesAdmin reply = new eForumRepliesAdmin(replyID);
replyID = JOptionPane.showConfirmDialog(null, "Are you sure that you want to delete the selected reply? " , "Delete replies", JOptionPane.YES_NO_OPTION);
if(replyID == JOptionPane.YES_OPTION){
reply.deleteReply();
JOptionPane.showMessageDialog(null, "Reply has been deleted successfully.");
SetUpJTableManageReplies();
}
}
}
});
return jTableManageReplies;
}
public void SetUpJTableManageReplies() {
DefaultTableModel tableModel = (DefaultTableModel) jTableManageReplies
.getModel();
String[] data = new String[5];
db.setUp("IT Innovation Project");
String sql = "Select forumReplies.reply_ID,forumReplies.reply_topic,forumTopics.topic_title,forumReplies.reply_content,forumReplies.reply_by from forumReplies,forumTopics WHERE forumReplies.reply_topic = forumTopics.topic_id ";
ResultSet resultSet = null;
resultSet = db.readRequest(sql);
jTableManageReplies.repaint();
tableModel.getDataVector().removeAllElements();
try {
while (resultSet.next()) {
data[0] = resultSet.getString("reply_ID");
data[1] = resultSet.getString("reply_topic");
data[2] = resultSet.getString("topic_title");
data[3] = resultSet.getString("reply_content");
data[4] = resultSet.getString("reply_by");
tableModel.addRow(data);
}
resultSet.close();
} catch (Exception e) {
System.out.println(e);
}
}
And this is my sql statement :
public boolean deleteReply() {
boolean success = false;
DBController db = new DBController();
db.setUp("IT Innovation Project");
String sql = "DELETE FROM forumReplies where reply_ID = " + replyID
+ "";
if (db.updateRequest(sql) == 1)
success = true;
db.terminate();
return success;
}
I called the repaint() to update the table data with the newest data in database and it works. I mean the data after deletion of certain row. However, the existing posts will keep on re-add. Then I add the removeAllElement method to remove all the existing posts because my sql statement is select * from table. Then, there is an error message which is ArrayIndexOutOfBoundsException. Any guides to fix this? Thanks in advance.
I called the repaint() to update the table data with the newest data
in database and it works.
There is no need to call repaint method when data is changed. Data change is handled by the Table Model (DefaultTableModel in this case.) And fireXXXMethods are required to be called whenever data is changed but you are using DefaultTableModel even those are not required. (Since by default it call these methods when ever there is a change.)
I think the problem is in the valuesChanged(..) method. You are getting the value at row 0 but not checking whether table has rows or not. So keep a constraint.
int viewRow = jTableManageReplies.getSelectedRow();
// Get the first column data of the selectedrow
if(jTableManageReplies.getRowCount() > 0)
int replyID = Integer.parseInt(jTableManageReplies.getValueAt(viewRow, 0).toString());

Searching for data in SQLite DB table

I have a text view in which user enters a string. I need to search for that string in a table and return a boolean value if a string matches.
I am not into SQL, so can anyone please help me figure out how to do it.
Assuming that you know the basics & the object db of type SQLiteDatabase exists in your DataAccessLayer, below is the function which returns true false based on whether the location exists or not?
public boolean IsRecordExists(long empid) throws SQLException
{
String where = "empid =" + empid;
Cursor mCursor = db.query(true, "employeeinfo", new String[] {"empid"}, where, null,null, null, null, null);
if (mCursor != null)
{
if(mCursor.moveToFirst())
return true;
else
return false;
}
return false;
}