I need to make a method getUserById witch will return 1 user by its id. I think that I need to use HashMap so here is my method :
public class UserDao {
private static final String SELECT_USERS = "select * from users_Alana";
public static List<User> getUsers(JdbcTemplate jdbcTemplate){
return jdbcTemplate.query(SELECT_USERS,new UserMapper());
}
private static class UserMapper implements RowMapper<User> {
#Nullable
public User mapRow(ResultSet resultSet, int i) throws SQLException {
User user = new User();
user.setId(resultSet.getInt("id"));
user.setName(resultSet.getString("name"));
user.setGender(resultSet.getString("gender"));
user.setAge(resultSet.getInt("age"));
return user;
}
}
public static void getUserById(int number) throws SQLException {
HashMap<Integer,User> getUser = new HashMap<Integer, User>();
if (getUser.containsKey(number)) {
System.out.println(getUser);
}
}
}
I call this method in a main class by UserDao.getUserById(2); Also I have a class User (with int id, age; String name, gender;) Constructor, getters and setters in it.
The result is nothing. How to solve it?
To get the user by id, I don't think you need a HashMap you can just use :
public static void getUserById(int id) throws SQLException {
UserDao dao = new UserDao();
List<User> users = dao.getUsers(jdbcTemplate);//This return a List or users
User user = user.stream()
.filter(u -> u.getId() == id)// filter the user by id
.findFirst()// if find then return the first
.orElseGet(User::new);// else return new User()
}
But it can be better to create a second query to get user by id :
private static final String SELECT_USERS_BY_ID = "select * from users_Alana WHERE id = ?1";
You need to return the User object from the getUser
public static User getUserById(int number) throws SQLException {
HashMap<Integer,User> getUser = new HashMap<Integer, User>();
return getUser.get(number);
}
You do need to populate the HashMap with the values though
Related
I have a query and it works well on the database. However, when I tried to take them as a Java object by using RowMapper, I get an invalid column name error. I checked everything, but I don't understand the reason why this error happening.
My query:
SELECT TEMP.SUMALLTXN, SUM(TEMP.SUMCARD), SUM(TEMP.SUMERRORTXN), SUM(TEMP.SUMERRORTXNCARD)
FROM
(SELECT
SUM(COUNT(*)) OVER() AS SUMALLTXN,
COUNT(mdmtxn.BIN) OVER (PARTITION BY mdmtxn.BIN) AS SUMCARD,
SUM(case when mdmtxn.MDSTATUS NOT IN ('1','9', '60') then 1 else 0 end) AS SUMERRORTXN,
SUM(case when mdmtxn.MDSTATUS NOT IN ('1','9', '60') then 1 else 0 end) OVER (PARTITION BY mdmtxn.BIN) AS SUMERRORTXNCARD
FROM MDM59.MDMTRANSACTION2 mdmtxn WHERE
mdmtxn.CREATEDDATE < TO_CHAR(SYSDATE - INTERVAL ':initialMinuteParameterValue' MINUTE ,'YYYYMMDD HH24:MI:SS') AND
mdmtxn.CREATEDDATE > TO_CHAR(SYSDATE - INTERVAL ':intervalMinuteParameterValue' MINUTE ,'YYYYMMDD HH24:MI:SS')
GROUP BY mdmtxn.MDSTATUS, mdmtxn.BIN
) TEMP
GROUP BY TEMP.SUMALLTXN
My RowMapper:
#Component
public class TotalTransactionsReportRw implements RowMapper<TotalTransactionsReportDto> {
#Override
public TotalTransactionsReportDto mapRow(ResultSet rs, int rowNum) throws SQLException {
return TotalTransactionsReportDto.builder()
.totalNumbersOfTransactions(rs.getString("SUMALLTXN"))
.totalNumbersOfCard(rs.getString("SUMCARD"))
.totalNumbersOfErrorTransactions(rs.getString("SUMERRORTXN"))
.totalNumbersOfErrorCard(rs.getString("SUMERRORTXNCARD"))
.build();
}
private static class TotalTransactionsDetailRwHolder {
private static final TotalTransactionsReportRw INSTANCE = new TotalTransactionsReportRw();
}
public static TotalTransactionsReportRw getInstance() {
return TotalTransactionsReportRw.TotalTransactionsDetailRwHolder.INSTANCE;
}
}
My Dto:
#Value
#Builder
#Data
public class TotalTransactionsReportDto {
private String totalNumbersOfTransactions;
private String totalNumbersOfCard;
private String totalNumbersOfErrorTransactions;
private String totalNumbersOfErrorCard;
}
And in my tasklet class I created a list to get all data from rowmapper:
#Slf4j
#Component
#RequiredArgsConstructor
public class NotificationTasklet implements Tasklet {
private final PofPostOfficeServiceClient pofPostOfficeServiceClient;
private final SequenceSysGuid sequenceSysGuid;
private final BatchProps batchProps;
private JdbcTemplate jdbcTemplate;
private String notificationMailSql;
private String totalTransactionsSql;
private String endOfHtmlString = "</table></body></html>";
private String endOfTableString = "</table>";
private String jobName = "vpos-notification";
private String tdClose = "</td>";`
#Override
public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
List<VposNotificationBatchDto> notificationList = getNotificationList();
List<TotalTransactionsReportDto> totalTransactionsList = getTotalTransactionsList();
AlertMailDto alertMailDto = createAlertMailDto(notificationList,totalTransactionsList);
if (!(notificationList.isEmpty())) {
sendMail(alertMailDto);
}
return RepeatStatus.FINISHED;
}
List<TotalTransactionsReportDto> getTotalTransactionsList() {
return jdbcTemplate.query(
totalTransactionsSql,
new TotalTransactionsReportRw());
}
#Autowired
public void setTotalTransactionsSql(#Value("classpath:sql/vposnotification/select_total_transactions_data.sql")
Resource res) {
int intervalnext = batchProps.getJobProps()
.get(jobName).getAlertProps().getIntervalMinuteParameterValue();
String intervalMinutes = String.valueOf(intervalnext);
int initialMinuteParameterValue = batchProps.getJobProps()
.get(jobName).getAlertProps().getInitialMinuteParameterValue();
String initialMinutes = String.valueOf(initialMinuteParameterValue);
this.totalTransactionsSql = SqlUtils.readSql(res);
this.totalTransactionsSql = this.totalTransactionsSql.replace(":initialMinuteParameterValue", initialMinutes);
this.totalTransactionsSql = this.totalTransactionsSql.replace(":intervalMinuteParameterValue", intervalMinutes);
}
#Autowired
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
The problem is that your query doesn't actually have columns SUMCARD, SUMERRORTXN and SUMERRORTXNCARD. Although there are DBMSes that alias SUM columns with the name of the column that is summed, Oracle is not one of them. IIRC, Oracle aliases it as, for example, "SUM(SUMCARD)" or maybe "SUM(TEMP.SUMCARD)". However, that is an implementation detail you should not rely on in my opinion.
To get the name you want to use, you need to alias your SUM columns explicitly, e.g. SUM(TEMP.SUMCARD) AS SUMCARD.
I have a simple Class with a inner class.
I want to set the following:
users[0][user_id]=8
users[1][user_id]=25
This is class:
public class ChatRequest {
private List<Userbean> users;
public List<Userbean> getUsers() {
return users;
}
public void setUsers(List<Userbean> users) {
this.users = users;
}
public static class Userbean {
private int user_id;
public int getUser_id() {
return user_id;
}
public void setUser_id(int user_id) {
this.user_id = user_id;
}
}
}
I tried it but without success.
How can I set the user id of the first user to 8 and the user id of the second user to 25?
These are java basic. Before refer to the Android SDK or something else please take a look into a java learning book/page.
However. Your "models" (or simple classes) are correct. To use these classes (and set the IDs you want) you need some instance of a UserBean first.
final ChatRequest.Userbean user0 = new ChatRequest.Userbean()
final ChatRequest.Userbean user1 = new ChatRequest.Userbean()
Then you can set the ID to it:
user0.setUser_id(8);
user1.setUser_id(25);
To finally add these users to the ChatRequest you need a instance of that as well:
final ChatRequest chatRequest = new ChatRequest();
Adding the users a simple call like that:
chatRequest.setUsers(Arrays.asList(user0, user1));
To be clear. These are the basic to create instances and set some values to classes/"models".
I think to answer your question we need some "preconditions". We assume that "someone" have already create some users and set it to the ChatRequest object which you receive in a "callback". To change some properties from the Userbean values can done in following way:
#Override
public void onChatRequestCreated(ChatRequest request) {
request.getUsers().get(0).setUser_id(8);
request.getUsers().get(1).setUser_id(25);
}
To set these values you should use this code:
users.get(0).setUser_id(8);
users.get(1).setUser_id(25);
Any idea on how to define indexes on data stored with Akiban's Persistit key/value store?
There isn't first class/API support for secondary indexes in Persistit. That isn't to say you can't create indexes though!
What is an index? In practice, all an index contains is another copy of the data. For example, in a relational database with a users table, an index on the first_name column would allow efficient look-up by first name. That can be achieved by storing an additional copy of the first name with the primary identifier to create a "link" back to the main row.
Here's an isolated example of that:
import com.persistit.*;
import com.persistit.exception.*;
import java.io.*;
import java.util.*;
public class IndexDemo implements AutoCloseable
{
public static class User implements Serializable
{
public int id;
public String firstName;
public String lastName;
public User() {
}
public User(int id, String firstName, String lastName) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
#Override
public String toString() {
return String.format("User(%d, %s, %s)", id, firstName, lastName);
}
}
private final Persistit db;
public IndexDemo() throws PersistitException {
Configuration c = new Configuration();
c.getBufferPoolMap().get(16384).setCount(32);
c.getVolumeList().add(new VolumeSpecification(
"IndexDemo.vol,create,pageSize:16384,initialPages:5,extensionPages:5,maximumPages:100"
));
this.db = new Persistit(c);
}
#Override
public void close() throws PersistitException {
db.close();
}
public Exchange userEx() throws PersistitException {
return db.getExchange("IndexDemo", "users", true);
}
public Exchange firstNamesEx() throws PersistitException {
return db.getExchange("IndexDemo", "firstNames", true);
}
// Save the user, both primary and secondary firstName index
public void saveUser(User u) throws PersistitException {
Exchange ex = userEx();
// Primary entries: key of ID and value of full User
ex.getKey().append(u.id);
ex.getValue().put(u);
ex.store();
// First name index: key of (name,ID)
ex = firstNamesEx();
ex.append(u.firstName).append(u.id);
ex.store();
}
// Look-up the user by ID
public User userByID(int id) throws PersistitException {
Exchange ex = userEx();
// Construct and fetch our key
ex.getKey().append(id);
ex.fetch();
// Careful: may not exist
if(!ex.getValue().isDefined()) {
return null;
}
// Otherwise get it from the value
return (User)ex.getValue().get();
}
// Index scan for users with firstName, look-up and return all matches
public List<User> usersByFirstName(String firstName) throws PersistitException {
List<User> users = new ArrayList<>();
Exchange ex = firstNamesEx();
// Iterate over only entires matching firstName
ex.append(firstName).append(Key.BEFORE);
while(ex.next()) {
// Index to second component (id) and decode
int id = ex.getKey().indexTo(1).decodeInt();
// And lookup the user
users.add(userByID(id));
}
return users;
}
public static void main(String[] args) throws PersistitException {
try(final IndexDemo demo = new IndexDemo()) {
System.out.println("No Transaction:");
runDemo(demo);
}
try(final IndexDemo demo = new IndexDemo()) {
System.out.println("Transaction:");
demo.db.getTransaction().run(new TransactionRunnable() {
#Override
public void runTransaction() throws PersistitException {
runDemo(demo);
}
});
}
}
public static void runDemo(IndexDemo demo) throws PersistitException {
demo.saveUser(new User(1, "John", "Doe"));
demo.saveUser(new User(2, "John", "Smith"));
demo.saveUser(new User(3, "Sally", "Jones"));
System.out.println(" User 1: " + demo.userByID(1));
System.out.println(" User 10: " + demo.userByID(10));
System.out.println(" Users named John:");
for(User u : demo.usersByFirstName("John")) {
System.out.println(" " + u);
}
}
}
Running yields this output:
No Transaction:
User 1: User(1, John, Doe)
User 10: null
Users named John:
User(1, John, Doe)
User(2, John, Smith)
Transaction:
User 1: User(1, John, Doe)
User 10: null
Users named John:
User(1, John, Doe)
User(2, John, Smith)
There isn't too much going on:
User POJO with a few attributes
Basic Persistit configuration and start-up
Helpers for saving, look-up by primary/ID and scan by first name
Demo usage of all the helpers
Main runs the demo both inside and outside of a transaction
All the pieces are there for building something extremely simple, like this demo, to something very sophisticated, like a complete SQL server.
I have two Classes.
one DAO that has an Arrraylist of Users (user is instace of User class)
and one method in another class that checks if there is a user with our input name or not
How can I use Hashmap (usernames, User) instead of Arraylist of Users?
public class UserDAO {
private static UserDAO instance;
private static String fileName = "sources/users.aaa";
//--------------------------------------------------------
private UserDAO(){
}
//--------------------------------------------------------
public boolean storeUsers(ArrayList<User> Users){
return IOFile.writeObject(Users, fileName);
}
//--------------------------------------------------------
public ArrayList<User> getUsers(){
ArrayList<User> Users = (ArrayList<User>) IOFile.readObject(fileName);
return Users;
}
//--------------------------------------------------------
public static UserDAO getInstance(){
if(instance == null)
instance = new UserDAO();
return instance;
}
}
and one method in another class that checks if there is a user with our input name or not:
User user = new User(firstName, lastName, userName, password);
ArrayList<User> users = UserDAO.getInstance().getUsers();
for (User user2 : users) {
if (user.equals(user2)){
system.out.println ("Error!!");
return;
}
}
users.add(user);
UserDAO.getInstance().storeUsers(users);
In this case, since you're just trying to check if the user exists, you could use a HashSet. A set has constant time lookups. So instead of your loop, it would just be users.contains(user).
You could use a map if you were looking up by something other than the actual User object, e.g. a mapping of names to users.
In either case, if you're using collection where you're checking contains, you must implement both equals and hashCode properly.
I have found myself in the need to override a static method, simply because it makes most sense, but I also know this is not possible.
The superclass, Entity.java:
abstract public class Entity<T> {
public Entity() {
//set up database connection
}
abstract public static Map<Object, T> getAll();
abstract public void insert();
abstract public void update();
protected void getData(final String query) {
//get data via database
}
protected void executeQuery(final String query) {
//execute sql query on database
}
}
One of the many concrete implementations, Account.java:
public class Account extends Entity<Account> {
private final static String ALL_QUERY = "SELECT * FROM accounts";
private final static String INSERT_QUERY = "INSERT INTO accounts (username, password) VALUES(?, ?)";
private final static String UPDATE_QUERY = "UPDATE accounts SET password=? WHERE username=?";
private String username;
private String password;
public Account(final String username, final String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(final String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(final String password) {
this.password = password;
}
#Override
public static Map<Object, Account> getAll() {
//return a map using the ALL_QUERY string, calls getData(string);
}
#Override
public void insert() {
//insert this using INSERT_QUERY, calls executeQuery(string);
}
#Override
public void update() {
//update this using UPDATE_QUERY, calls executeQuery(string);
}
}
I haven't been going in depth explaining the code, but any general feedback on it would also be appreciated, I hope the comments explain enough.
So basically I think we can all agree that using Account.getAll() makes more sense over new Account().getAll() (if I would introduce a dummy syntax for it).
However I do want to have it extend the Entity class, currently it is only for convienience, but later on I may have to use sets/lists/multisets of Entity and perform an update() action on all of them, for example if I would build some queue that performances all updates every minute.
So well, is there a way to construct getAll() correctly?
Regards.
You could have separate classes for operations on all elements:
abstract public class Collection<T extends Entity<T>> {
abstract public static List<T> getAll();
public void printAll() {
// Print all entries of List obtained from getAll()
}
}
Which you could use as:
public class Accounts extends Collection<Account> {
#Override
public List<Account> getAll() {
//return a list using the ALL_QUERY string, calls getData(string);
}
}
It doesn't seems to me that it is really "simply because it makes most sense".
Tying persistence at your entity is not a good idea. There are already lots of patterns that give an appropriate design on this problem.
For example, in Domain Driven Design, "Persistence Ignorance" is what people trying to achieve. Consider making a Repository for each of your entity:
interface Repository<T> {
List<T> findAll();
void insert(T);
void update(T);
}
so you can override it by whatever way you want:
interface UserRepository extends Repository<User> {
// some other methods which is meaningful for User
User findByLoginName(String loginName);
}
class UserRepositoryImpl implements UserRepository {
List<User> findAll() {
// call whatever query
}
void insert(T){...}
void update(T){...}
User findByLoginName(String loginName) {...}
}
With a proper design and a component to handle the retrieval/storage of entity, you can have a less-persistence-coupled entity, and with repository that can perform proper "overriding".