I have a Table Like below
I run a Query to get Values in Table as Below
SELECT Id, UserName, UserId, Password,
CASE Status WHEN 1 THEN 'Active' ELSE 'Inactive' END AS Status
FROM users
Now I Java code for the Above Query is as below.
String[] arrUsersList[] = new String[100][5];
String[] arrUsersTem = new String[5];
pstmt = conn.createStatement(rs.TYPE_FORWARD_ONLY, rs.CONCUR_READ_ONLY);
rs = pstmt.executeQuery(strSQL);
while(rs.next())
{
arrUsersTem[0] = rs.getString("Id");
arrUsersTem[1] = rs.getString("UserName");
arrUsersTem[2] = rs.getString("UserId");
arrUsersTem[3] = rs.getString("Password");
arrUsersTem[4] = rs.getString("Status");
arrUsersList.add(arrUsersTem);
}
My Question is
I know I should use two dimensional array for getting the values from Recordset. I also know I am Doing it wrong way.What is the right way of taking records from Result set for the above.
Is array right option or i should use ArrayList or Some thing else.
Thanks for Reply.
Java is OOP language, so common way is to create class describing entities of your table and form Collection with this class objects
class Account {
private long id;
private String userName;
private String userId;
private String password;
private boolean status;
// getters, setters
}
List<Account> accountList = new ArrayList();
Account account;
while(rs.next()) {
account = new Account();
account.setId(rs.getLong("Id"));
account.setUserName(rs.getString("UserName"));
account.setUserId(rs.getString("UserId"));
account.setPassword(rs.getString("Password"));
account.setStatus(rs.getBoolean("Status"));
accountList.add(account);
}
You should create a User bean that contains fields for each of your database columns. Then create a List of User beans and do this:
List<User> users = new ArrayList<User>();
while(rs.next()) {
User user = new User();
user.setId(rs.getString("Id"));
user.setUsername(rs.getString("UserName"));
//More fields here
users.add(user);
}
You will then be left with a list of Users rather than a confusing 2d array
Since you result set can be of any size, you should not use Array, you should use Collection (or any derived implementation).
First you should create a class that represent the tuple you are retrieving:
public class User {
// fields
private int id;
private int userId;
private String username;
private String password;
private String status;
// constructor
public User(ResultSet rs) {
id = rs.getInt("Id");
// the same for the other fields...
}
}
Second and last, when iterating just create a new instance for each row/tuple, and add the resulting object to a collection that will grow as needed.
List<User> users = new ArrayList<User>();
while(rs.next())
{
users.add(new User(rs));
}
I would create a class User:
public class User {
private int id;
private String userName;
private String userId;
private String password;
private boolean active;
// getters & setters...
}
And then create Users like this:
SQL:
SELECT Id, UserName, UserId, Password, Status FROM users
Java:
List<User> users = new ArrayList<User>();
while (rs.next()) {
User user = new User();
user.setId(rs.getInt(1));
user.setUserName(rs.getString(2));
user.setUserId(rs.getString(3));
user.setPassword(rs.getString(4));
user.setActive(rs.getInt(5)>0);
users.add(user);
}
Try this:
while(rs.next()) {
account = new Account();
account.setId(rs.getLong("Id"));
account.setUserName(rs.getString("UserName"));
account.setUserId(rs.getString("UserId"));
account.setPassword(rs.getString("Password"));
account.setStatus(rs.getBoolean("Status"));
accountList.add(account);
}
Related
public class UserList {
private String id;
private String email;
private String userType;
private String rolls;
private String partner;
private Integer customersLinked;
private String position;
private String status;
#Autowired
ICustomerRepository customerRepository;
public UserList (Users user){
this.id = user.getId();
this.email = user.getEmail();
this.userType = user.getUserType();
this.rolls = user.getRolls();
this.partner = user.getPartner();
List<Customer> customersLinked = customerRepository.findAllByLinkedUsersIn(user.getId());
this.customersLinked = 0;
this.position = user.getPosition();
this.status =user.getStatus();
}
//Getter and Setter
}
This class is used as a list in the frontEnd ,get specific data ,not send all the data
#RequestMapping(value = "usersLinked/{id}/{type}", method = RequestMethod.GET)
public Object getUsersLinkedById(#PathVariable("id") String id,#PathVariable("type") Integer type) {
List<String> users = null;
switch (type) {
case 0:
users = usersRepository.findAll().stream().map(m -> m.getId()).collect(Collectors.toList());
break;
}
//Add userList
List<UserList> userList = new ArrayList<>();
if(users != null)
{
users.forEach(userId ->
{
Optional<Users> user = this.usersRepository.findById(userId);
userList.add(new UserList(user.get()));
});
}
return userList;
}
}
As you can see from above I am calling al the data from the user repository and sending it the list
My customer repository
public interface ICustomerRepository extends MongoRepository<Customer, String> {
Customer findByBusinessInformation_businessName(String businessName);
List<Customer> findByBusinessInformation_partnerAssigned(String partnerAssigned);
#Query("{ 'LinkedUsers' : ?0 }")
Customer findByLinkedUsers(String id);
List<Customer> findAllByLinkedUsersIn(String id);
}
In the userList I get the error when I add the logic wityh the customerRepository ,without the repository there everything is working(Want to use the repository to get an array of customer and then get the size() of the array and add it to linkedCustomers). Am I missing sommething
You are trying to inject the field customerRepository using Autowired annotation, but your class is not injectable.
You can add an annotation #Repository on your class UserList
Or use constructor injection (better way to inject your beans)
You're probably missing the #repository annotation on top of your repository class.
Another unrelated word of advice:
In your controller you use findAll and filter in java to keep only the ids.
Then you go to the same repository and perform another query per user-id from above.
This is a causing you to create multiple database calls which are one of the most expensive operations you can do, when you already have all your data from the first single query...
Also if you're only looking at the bottom part of the function you don't event need a query per each user-id (when you have a list of user ids as input), you can create a query that uses the 'in' convention and pass a list of user-ids to create a single db call.
First of all I would get rid of #Autowired ICustomerRepository customerRepository; in UserList class. It doesn't belong there. The counting of linked customers should be executed in ICustomerRepository and the result to be passed into UserList via the constructor.
e.g.
public class UserList {
private String id;
private String email;
private String userType;
private String rolls;
private String partner;
private Long customersLinked; //better use Long instead of Integer
private String position;
private String status;
// constructor takes the number of linked customers as parameter
public UserList (Users user, Long customersLinked ) {
this.id = user.getId();
this.email = user.getEmail();
this.userType = user.getUserType();
this.rolls = user.getRolls();
this.partner = user.getPartner();
this.customersLinked = customersLinked;
this.position = user.getPosition();
this.status =user.getStatus();
}
//Getter and Setter
}
and then create the count query in ICustomerRepository
e.g.
public interface ICustomerRepository extends MongoRepository<Customer, String> {
//other methods
Long countByLinkedUsersIn(String id); //not so sure if this query works in mongo
}
and finally in your controller
Optional<Users> user = this.usersRepository.findById(userId);
Long count = this.usersRepository.countByLinkedUsersIn(userId);
userList.add(new UserList(user.get(), count));
P.S. I have a doubt for the query method: Long countByLinkedUsersIn(String id);. Usually when repository methods have "In" in their names, countByLinkedUsersIn, then it is expected as parameter a List and not a single user id. However if your previous method List<Customer> findAllByLinkedUsersIn(String id); worked for you, then this one should work too.
I am saving my data into a selected database with my default method. However, there is 1 entity that i want to save on different table's column. How should i change on my method?
LoginBean.java
private String fullName_;
private String gender_;
private String phoneNumber_;
private String IC_;
private String email_;
private String Address_;
private String password_;
private String course;
List<String> courseOption;
public LoginBean(){
courseOption = new ArrayList<>();
courseOption.add("Information Technology");
courseOption.add("Business Management");
courseOption.add("Engineering");
courseOption.add("Design");
//getter and setter
public String saveUserStudent(LoginBean loginBean){
UserDao dao = new UserDao();
User user = new User();
user.setFullName(loginBean.getFullName_());
user.setGender(loginBean.getGender_());
user.setPhoneNumber(Integer.parseInt(loginBean.getPhoneNumber_()));
user.setIc(loginBean.getIC_());
user.setEmail(loginBean.getEmail_());
user.setAddress(loginBean.getAddress_());
user.setPassword(loginBean.getPassword_());
dao.saveUserStudent(user);
Map<String,Object> sessionMapObj = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
sessionMapObj.put("msg", "Data "+user.getIc() +"successfull!");
my dao.saveUserStudent(user) is the method name that has been saved on the directed database. Is there anything i should add or change on the source code?
I'm currently developing a web application in Java which will be accessed by multiple users at the same time and as such need to store userdata in order to tailor the application to their individual requirements (such as what company they are apart of etc).
There are 2 classes that i use to manage this. User, MainSystem detailed below:
User
#Entity
public class User implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String firstName;
private String lastName;
private String username;
private String password;
private String type;
private String company;
private String DOB;
private String email;
private int PayrollId;
public User(String firstName, String lastName, String username, String password, String type, String company, String DOB, String email) {
this.firstName = firstName;
this. lastName = lastName;
this.username = username;
this.password = password;
this.type = type;
this.company = company;
this.DOB = DOB;
this.email = email;
}
MainSystem:
public class MainSystem {
public UserController userController;
private UserRepository userRepository;
private static ThreadLocal<User> loggedInUser = new ThreadLocal<>();
public DbController dbController;
public MainSystem(){
userController = new UserController(userRepository);
loggedInUser.set(new User());
}
public Boolean Login(String username, String password) {
if(userController.checkUser(username,password)){
User aUser = userController.getUser(username);
setLoggedInUser(userController.getUser(username));
VaadinSession.getCurrent().setAttribute("username",loggedInUser.get().getUsername());
System.out.println("Logged in User: "+loggedInUser.get().getUsername());
return true;
}
else {
return false;
}
}
public static void setLoggedInUser(User user){
loggedInUser.set(user);
}
public static User getLoggedInUser() {
return loggedInUser.get();
}
Ideally what i'd like to do is access the ThreadLocal variable from another class, for instance the ViewProfile.View:
public class EditProfileView extends VerticalLayout implements View {
MainSystem main = new MainSystem();
NavigatorUI aUI = new NavigatorUI();
User aUser = main.getLoggedInUser();
TextField username = new TextField("Username");
TextField Id = new TextField("Id");
TextField email = new TextField("Email");
TextField firstName = new TextField("First name");
TextField lastName = new TextField("Last name");
TextField type = new TextField("Type");
PasswordField oldPassword = new PasswordField("Current Password");
PasswordField changePassword1 = new PasswordField("New Password");
PasswordField changePassword2 = new PasswordField("Confirm Password");
private UserController userController;
private UserRepository userRepository;
public EditProfileView() {
setDefaultComponentAlignment(Alignment.MIDDLE_CENTER);
userController = new UserController(userRepository);
setStyleName("backgroundImage");
setMargin(true);
setSizeFull();
addComponent(aUI.getHeader());
FormLayout content = new FormLayout(generateInfo());
Panel aPanel = new Panel("Edit User",content);
aPanel.setWidthUndefined();
content.setMargin(true);
aPanel.setStyleName(ValoTheme.PANEL_WELL);
addComponent(aPanel);
}
#Override
public void enter(ViewChangeListener.ViewChangeEvent event) {
try {
aUser = main.getLoggedInUser();
System.out.println( aUser.getUsername());
Id.setValue(aUser.getId().toString());
username.setValue(aUser.getUsername());
firstName.setValue(aUser.getFirstName());
lastName.setValue(aUser.getLastName());
type.setValue(aUser.getType());
email.setValue(aUser.getEmail());
aUI.setUserMenu();
aUI.refreshPayroll();}
catch (Exception e){
System.out.println(e.getMessage());
}
}}
However, i'm finding that it is presenting me with a "null" value? I fear i may have missunderstood how ThreadLocal works. but essentially what i'm trying to achieve is to Store an instance relevant variable of the User.Class in MainSystem for other classes to use?
Any help would be appreciated.
My Solution:
My solution to this was to store the User.class in a VaadinSession Attribute like so:
public Boolean Login(String username, String password) {
if(userController.checkUser(username,password)){
User aUser = userController.getUser(username);
VaadinSession.getCurrent().setAttribute("user",aUser);
VaadinSession.getCurrent().setAttribute("username",loggedInUser.get().getUsername());
System.out.println("Logged in User: "+loggedInUser.get().getUsername());
return true;
}
else {
return false;
}
}
Then in other classes if i want to use that attribute i retrieved it like so:
#Override
public void enter(ViewChangeListener.ViewChangeEvent event) {
try {
aUser = (User)VaadinSession.getCurrent().getAttribute("user");
}
catch (Exception e){
System.out.println(e.getMessage());
}
}
The problem is that there's no guarantee that MainSystem.Login() and EditProfileView.enter() will happen on the same thread. Every user action is processed as a separate HTTP request that the servlet container will run on any available thread.
For this kind of functionality, I would instead recommend storing the user information in the HTTP session. If you don't have any custom servlets or such, you could instead have a an field that contains the user object in your own custom UI class. Vaadin takes care of making UI.getCurrent() always return the right value in all code that is run through Vaadin.
If you instead also are integrating with other servlet functionality, you could store the user in the HttpSession instead. Generic servlet code can find the session through the getSession() method in e.g. servlet requests and response. In code run by Vaadin, you can use VaadinSession().getCurrent().getSession() to get a WrappedSession instance that is based on to the same HttpSession data.
There is also another approach. Instead it could be possible to make #SessionScoped user service, and either #Inject or #Autowire that depending whether you are using CDI or Spring. When doing this way, it will be the bean manager that takes care of binding correct entity with your view.
For Example:
ArrayList1 = {userid1, userid2, userid1, userid4, userid1, userid3, userid2, userid4, userid4, userid4, userid2};
ArrayList2 = {username1, username2, username3, username4};
Mapping these two array so that whenever I call ArrayList1.get(0).getUserName(), it should provide me with username1.
public class User {
String username;
public User(String username)
{
this.username = username;
}
/**
* #return the username
*/
public String getUsername() {
return username;
}
/**
* #param username the username to set
*/
public void setUsername(String username) {
this.username = username;
}
}
userid1, userid2... must be User objects
User userid1 = new User("username1");
User userid2 = new User("username2");
Initialize all the user objects
ArrayList1 = {userid1, userid2, userid1, userid4, userid1, userid3, userid2, userid4, userid4, userid4, userid2};
Then you can call
String username = ArrayList1.get(0).getUserName();
this will return username1
There is a better way to do that and that is by using HashMap:
//create your custom object which will be mapped
public class User{
public String userId;
public String userName;
}
ArrayList<String> userKeys = new ArrayList<String>();
HashMap<String, User> users = new HashMap<String, User>();
Now using a userKey, you can access its corresponding userData;
Example:
User user = users.get("yourKey");
I think you should use :
List<List<T>> = ArrayList<ArrayList<T>>;
T is the class of you UserName.
Use HashSet instead of arraylist. Set does not allow duplicate.
I'm learning Hibernate and Play framework (also add Java into account...). I'm having problems saving this kind of entity
#Entity
#Table(name="users")
public class User extends Model {
#Required
public String username;
#Column(name="user_displayname",nullable=true)
public String displayname;
#Password
public String user_password;
#Email
#Column(name="user_email",nullable=false,unique=true)
public String user_email;
public String user_salt;
public Date user_joindate;
#ManyToOne
#JoinTable(name="users_meta")
public UserMeta userdata;
#Required
public boolean user_isActive;
#OneToOne(targetEntity=UserPhotos.class,cascade=CascadeType.ALL)
#JoinColumn(name="id",referencedColumnName="userID")
public UserPhotos userPhoto;
#ManyToMany(cascade=CascadeType.ALL)
#JoinTable(name="links_rol2user")
public List<Rol> rol;
public User (String username, models.Pass password, String user_email) {
this.username = username;
this.user_password = password.getHashedPassword();
this.user_salt = password.getUserHash();
this.user_email = user_email;
this.user_joindate = new Date();
this.user_isActive = false;
}
This is my code when I'm registering a user
// check if the validation has errors
if(validation.hasErrors()) {
params.flash(); // add http parameters to the flash scope
validation.keep(); // keep the errors for the next request
register();
} else {
Cache.delete(uuid);
Pass pass = new Pass(password,new Date().toString());
User newUser = new User(firstName, pass, email);
UserMeta utest = new UserMeta(newUser.id);
utest.setUserTownID(pueblos);
newUser.setUserMeta(utest);
newUser.save();
Logger.info("NewUser ID : %s", newUser.getId());
// UserMeta userInfo = new UserMeta(newUser.getId());
// userInfo.setUserTownID(pueblos);
// userInfo.save();
// TODO salvar foto a null
// Confirmation left
Cache.set("thankyou", "alright!", "3mn");
thankyou();
}
I'm trying to save the userMeta, it does creates a new record when I set the userMeta object into newUser (not visible right now), but it doesn't insert the new ID created in newUser.
What kind of relation do I need? before I tweaked the code as it is now, it was a OneToOne relationship, worked quite well, but now when I was completing the register functions it kinda hit me that I needed to save userMeta object too..
If you need more info let me know, I don't know if I explained it well or not, just trying to get the hang of how Hibernate do relations, etc.
Adding UserMeta:
*/
#Entity
#Table(name="users_meta")
public class UserMeta extends Model {
#Lob
#Column(name="userBio")
public String userBio;
#Column(name="userPhotoID",nullable=true)
public Long userPhotoID = null;
#Column(name="userRoleID", nullable=false)
public Long userRoleID = 2L;
#Lob
public String userDescription;
#Column(name="userViews", nullable=false)
public Long userViews = 0L;
#Column(name="userFavoriteCount", nullable=false)
public Long userFavoriteCount = 0L;
#Column(name="userTotalComments", nullable=false)
public Long userTotalComments = 0L;
#Column(name="userTotalUploadedVideos", nullable=false)
public Long userTotalUploadedVideos = 0L;
public Long userTownID;
public Long userID;
public UserMeta() {}
public UserMeta(Long userid) {
this.userBio = "El usuario no ha escrito nada todavia!";
this.userDescription = "El usuario todavia no se ha describido!";
this.userID = userid;
}
public Long getUserTownID() {
return userTownID;
}
public void setUserTownID(Long userTownID) {
this.userTownID = userTownID;
}
}
// pass model
public class Pass {
protected String hashed;
protected String userHash;
public Pass(String passwordToHash, String salt) {
StringBuffer passSalt = new StringBuffer(passwordToHash);
this.userHash = DigestUtils.md5Hex(salt);
passSalt.append(this.userHash);
passSalt.append(Play.configuration.getProperty("application.passwordSalt"));
this.hashed = DigestUtils.sha512Hex(passSalt.toString());
}
public String getHashedPassword() {
return this.hashed;
}
public String getUserHash() {
return this.userHash;
}
}
There seems to be a lot going on there! But from what I can tell, you problem is with the id that you are passing into the UserMeta.
As you are extending Model, the id is being generated by the Model class. However, this is not set until after the entity is saved to the database (as the id is auto-generated by the database).
Therefore, because you are passing the id into the UserMeta before the User object is saved, the value of id will be null.
If you can save the User object before you create your UserMeta object, your code should work.