How to get just a string from room database - java

I need to get a string from my room database and set it as text in a textview i'm using this code in my dao
#Query("SELECT question, question_heat, question_gender FROM questions WHERE question_heat = :heat AND question_gender = :gender" +
" ORDER BY RANDOM() LIMIT 1")
String getQuestion(int heat, int gender);
i just want to get a random question from my question database.I get this error:
error: Not sure how to convert a Cursor to this method's return type String getQuestion(int heat, int gender);
in the build output says the error is in the query
i'm really new in room i was using sqlopenhelper for a while and i don't really know what to do here.
i found some codes in google but they were for lists of data and i want to get just a string.

You must select only question column. Try this way:
#Query("SELECT question FROM questions WHERE question_heat = :heat AND question_gender = :gender ORDER BY RANDOM() LIMIT 1")
String getQuestion(int heat, int gender);

You select 3 columns and expect to get a string?
I think you must do this :
#Query("SELECT * FROM questions WHERE question_heat = :heat AND question_gender = :gender" +
" ORDER BY RANDOM() LIMIT 1")
QuestionEntity question(int heat, int gender);
and then convert it manually in repository with
String result = question.getQuestion + question.getQuestionHeat + question.getQuestionGender ;

Related

How to create a dynamic WHERE clause for a query using an array list

I have a List<String> of categories and for each category, I want to add them to my WHERE clause by combining with AND operator like: SELECT question_id FROM question WHERE category = categ1 AND category = categ2 AND category = ...
Since the size of the categories list is changing, I cannot do something like this:
String sql = "SELECT question_id FROM question WHERE category = ? AND category = ?";
jdbcTemplate.query(sql, stringMapper, "categ1", "categ2");
How can I achieve what I want?
Either check if JDBC Template from Spring handle that for you using a syntax which could be something like (from the doc, I don't think it does)
SELECT question_id FROM question WHERE category in (?...)
Or write your own query with the problems that may arise:
List<Object> parameters = new ArrayList<>(categories.size());
StringBuilder sb = new StringBuilde("SELECT question_id FROM question WHERE 1=1");
if (!categories.isEmpty()) {
if (categories.size() == 1) {
sb.append(" and category = ?");
} else {
sb.append(" and category in ");
sb.append(categories.stream()
.map(ignored -> "?")
.collect(joining(", ", "(", ")")));
sb.append(")");
}
parameters.addAll(categories);
}
Object[] paramArray = parameters.toArray();
jdbcTemplate.query(sb.toString(), stringMapper, paramArray);
Notes:
some security/quality tool may report SQL issues because you are writing a dynamic SQL.
Oracle put a limit on 1000 elements per IN. You would have to partition categories per group of 1000 (or less).
I used a stream() in a more or less strange fashion in order to generate the "?". If you use commons-lang3, you can replace it by "(" + StringUtils.repeat("?", ", ", categories.size()) + ")" (the example in the javadoc was probably done with this kind of use).
if you only have category as single criteria, you may probably remove the 1=1 as well as the and.
I believe this may work for you:
// The SQL Query
String sql = "SELECT question_id FROM question";
// Create the WHERE clause based on the number of items in List...
StringBuilder whereClause = new StringBuilder(" WHERE ");
StringBuilder ps = new StringBuilder("");
for (int i = 0; i < categories.size(); i++) {
if (!ps.toString().isEmpty()) {
ps.append(" AND ");
}
ps.append("category = ?");
}
whereClause.append(ps.toString()).append(";");
//Append the WHERE clause string to the SQL query string
sql = sql + whereClause.toString();
//System.out.println(sql);
/* Convert the categories List to an Object[] Array so as to
pass in as varArgs to the jdbcTemplate.query() method. */
Object[] psArgs = categories.toArray(new Object[categories.size()]);
jdbcTemplate.query(sql, stringMapper, psArgs);

Get PostgreSql table size on disk (byte) in ORMlite

I use ORMLite in a Java application, in order to deal with a PostgreSql DataBase.
I want to get the space on the disc used by a table of DataBase.
It seems that OrmLite doesn't have a specific method to get it, so I tried without success:
final String TABLE_NAME = "a_table_name_of_db";
//1)
String SQL = "SELECT pg_relation_size('" + TABLE_NAME + "');" ;
int result = OGGETTO_DAO.executeRaw(SQL);
//2)
String SQL = "SELECT pg_table_size('" + TABLE_NAME + "');" ;
int result = OGGETTO_DAO.executeRaw(SQL);
//3 - it was just a try...)
SQL = "SELECT pg_table_size('" + TABLE_NAME + "');" ;
GenericRawResults<String> ARRAY = OGGETTO_DAO.queryRaw(SQL);
String result= ARRAY.getFirstResult();
With 1) and 2) I get always -1, with 3) I get a cast exception;
I I use the command 'pg_relation_size' or 'pg_table_size' by command line (linux - by psql prompt), it works properly.
What am I wrong?
Thank you
UPDATE - WORKING SOLUTION:
Now it works! Solution, as per accepted answer below, is:
final String TABLE_NAME = "a_table_name_of_db";
String SQL = "SELECT pg_table_size('" + TABLE_NAME + "');"
final long RESULT = OGGETTO_DAO.queryRawValue(SQL); //in bytes
int result = OGGETTO_DAO.executeRaw(SQL);
Yeah that's not right. Looking at the javadocs for executeRaw(...) they say that it returns the number of rows affected not the result.
SQL = "SELECT pg_table_size('" + TABLE_NAME + "');" ;
GenericRawResults ARRAY = OGGETTO_DAO.queryRaw(SQL);
String result= ARRAY.getFirstResult();
Looking at the javadocs for queryRaw(...), the problem here is it returns a GenericRawResults<String[]> and not <String>. It returns a collection of raw results, each row being represented by a string array. I'm really surprised that your code even compiles.
It should be:
GenericRawResults<String[]> ARRAY = OGGETTO_DAO.queryRaw(SQL);
String result= ARRAY.getFirstResult()[0];
Probably the best way to do this is to use queryRawValue(...) which performs a raw query and returns a single value.
// throws an exception if there are no results or if the first one isn't a number
long size = OGGETTO_DAO.queryRawValue(SQL);

Discord Java JDA | deleting data from SQLite / getting data from SQLite [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I'm trying to make a ticket-based support system and I would like to know how to read and delete data from a SQLite table.
The system will work like this:
You click on a reaction and the bot checks if you already have a dedicated channel, if not it will create one.
If you close the ticket by clicking on a reaction in your personal channel, the channel and your data will be deleted.
That's my code so far:
public void onMessageReactionAdd(MessageReactionAddEvent event) {
if(!event.getUser().isBot()) {
if(event.getChannel().getIdLong() == 747412032281772033l && event.getReactionEmote().getEmoji().equals("\uD83C\uDFAB")) {
ResultSet set = LiteSQL.onQuery("SELECT channelid FROM ticketchans WHERE guildid = " + event.getGuild().getIdLong() + " AND userid = " + event.getUserIdLong());
try {
Long user = set.getLong("userid");
if(!(user == event.getUserIdLong())){
Category cat = ((GuildChannel) event.getChannel()).getParent();
TextChannel chan = cat.createTextChannel(event.getMember().getEffectiveName() + "'s TicketChannel").complete();
EmbedBuilder builder = new EmbedBuilder();
builder.setDescription("Hi " + event.getMember().getAsMention() + ", bitte beschreibe hier detailiert dein Anliegen. Wenn du dein ticket schliessen willst klicke auf das X");
builder.setColor(Color.decode("#910cc9"));
chan.sendMessage(builder.build()).queue(Message -> {
Message.addReaction("\u274C").queue();
});
set.next();
LiteSQL.onUpdate("INSERT INTO ticketchans(guildid, channelid, userid) VALUES(" +
event.getGuild().getIdLong() + ", " + event.getChannel().getIdLong() + ", " + event.getUserIdLong() + ")");
event.getChannel().sendMessage(event.getUser().getAsMention() + " TicketChannel eröffnet!").complete().delete().queueAfter(4, TimeUnit.SECONDS);
}
}catch (SQLException e) {}
}
if(event.getReactionEmote().getEmoji().equals("\u274C")) {
//delete data in table event.getGuild().getGuildChannelById(event.getChannel().getIdLong()).delete().reason("").queue();
}
}
}
Getting Data from SQLite
Most of this applies to SQL in general and isn't specific to SQLite.
First off, a SELECT statement consists of different parts.
SELECT columns FROM table WHERE condition;
For columns you have to fill in the names of the columns you want to get from your table. Pretty self-explanatory.
If you want to select more than one column, you just have to list them with commas, like this:
SELECT column1, column2, column3 FROM table WHERE condition;
In order to select every column of your table you just write * instead of the columns.
SELECT * FROM table WHERE condition;
Note: You can only access columns in your ResultSet if you selected them in your statement. If you select channelid you won't be able to get userid, unless you select it as well. (SELECT channelid, userid FROM table WHERE condition;)
You seem to understand the WHERE part so I will skip it. In case you need some more help or want to expand your usage of SQLite even more, you may check out some tutorials online.
Now, after writing your correct SELECT statement it's time to access the data in Java.
Therefore, you have to loop through your ResultSet.
ResultSet rs = LiteSQL.onQuery(
"SELECT channelid, userid
FROM ticketchans
WHERE guildid = " + event.getGuild().getIdLong() + "
AND userid = " + event.getUserIdLong()
);
// loop through the result set
while (rs.next()) {
Long userid = rs.getLong("userid");
Long channelid = rs.getLong("channelid");
}
You now have the data you need and can use it for whatever you want.
Deleting Data from SQLite
Most of this applies to SQL in general and isn't specific to SQLite.
The DELETE statement has a similar structure to the SELECT statement although it lacks the columns (of course).
DELETE FROM table WHERE condition;
As explained in the first part, you have to choose the table you want to delete data from and then narrow it down using conditions.
In your case, deleting a specific ticket would be like this:
DELETE FROM ticketchans WHERE guildid = GID and userid = UID and channelid = CID;
If you don't use all three IDs in the condition, you might end up deleting all tickets of a guild or of an user. Since the channelid is always unique you could possibly skip the userid = UID part, but the details are up to you.
As already mentioned, if you want more specific statements or need some variations, check out a tutorial of your liking. (The one provided is just an example, use whatever you are comfortable with.)
On another note: I would advice not using .complete() but .queue() instead.
If you want to know why and how, check out this page.

How do you access the value of a DQL count() query in Java Program

I want to get to the value I am finding using the COUNT command of DQL.Normally I enter the column name I want to access into the getInt() getString() method. What I'm supposed to do when there is no specific colomn name.
{
String query = "select count(*) as count from dm_user;";
return query;
}
Code to fetch the result
{
IDfCollection total = dql.execute(session, IDfQuery.DF_READ_QUERY);
while (total.next()){
cint = total.getInt("count");
}
Tomcat Result
DfException:: THREAD: http-8080-2; MSG: [DM_QUERY_E_SYNTAX]error: "A Parser Error (syntax error) has occurred in the vicinity of: select count(*) as count"; ERRORCODE: 100; NEXT: null
You are using count which is a keyword for your column custom name, the error you posted clearly says it: A Parser Error (syntax error)
This will do
select count(*) as quantity from dm_user;
and fetching result like
IDfCollection total = dql.execute(session, IDfQuery.DF_READ_QUERY);
while (total.next()){
cint = total.getInt("quantity");
will work
While #Miki answered it already but I like to add one small thing here that below code should work too if you haven't specified any alias.
{
IDfCollection total = dql.execute(session, IDfQuery.DF_READ_QUERY);
while (total.next()){
cint = total.getInt("count(*)");
}
}

JPA OR condition with single value

I have a table company: companyId number, companyName varchar, address nvarchar.
I want to achieve a goal that user can query to fetch company either using a id or company name, image there is a search box, user only has to input a single value, then it will fetch company information.
I wrote an repository
#Query(value = "select c from CompanyBasicInfo c where c.companyID = ?1 or c.companyName = ?1 ")
List<CompanyBasicInfo> findByCompanyIDOrCompanyName(#PathVariable String input);
But when I query, I got an error: Parameter value [10083769] did not match expected type [java.lang.Long (n/a)]
How can I solve this problem? Most of the materials available are something like
findByFirstnameOrLastname which uses two values. Thanks a lot!
If none of the companies have a name which consists only of digits, you can create 2 methods (by companyId / by company name) and check wether your input is a number.
If you do not want to do this, you can use the "2 params" version :
List<CompanyBasicInfo> findByCompanyIDOrCompanyName(Long companyId, String companyName);
Then parse your input :
List<CompanyBasicInfo> find(String input) {
Long companyId = null;
try {
companyId = Long.valueOf(input);
} catch(Exception ignored){}
return repository.findByCompanyIDOrCompanyName(companyId, input);
}
This is not a problem of parameters amount but of its type
You can try to treat companyId as String in query using cast function like here.
How do I write hql query with cast?
Your code will look like
#Query(value = "select c from CompanyBasicInfo c where cast(c.companyID as String) = ?1 or c.companyName = ?1 ")
List<CompanyBasicInfo> findByCompanyIDOrCompanyName(#PathVariable String input);

Categories