I have a set of SQL queries and a corresponding POJO object with a constructor.
Ex.
Student student = new Student(rs.getString("FNAME"), rs.getString("LNAME"), rs.getString("GRADE"));
Currently I'm mapping the column in result set to a field manually. I would like to make this generic so I can do something like new Student(rs.getRow()) and then I can map it via some kind of configuration file. There could be N number of fields in select query and order doesn't necessarily match with order defined in the constructor.
I would like to have control over the SQL since it could have lot of joins so I am not sure if an ORM would work here. I strictly want something that could map the resultset columns to a field.
I would like to add annotations in my Student class for mapping
public class StudentRowMapper implements RowMapper<YourStudentPojo> {
#Override
public YourStudentPojo mapRow(final ResultSet rs, final int arg1) throws SQLException {
final YourStudentPojo item = new YourStudentPojo();
item.setFName(rs.getString("FNAME"));
return item;
}
Similar to this FName, you can set the other values in your pojo. No need for constructor. Just if you make changes in Pojo then corresponding changes must be done in this method.
This does seem like a textbook example of a place to use JPA or a similar ORM technology.
However, if you are set on just doing this with annotations, you can create your own annotations - http://www.mkyong.com/java/java-custom-annotations-example/ is a pretty good tutorial on doing so.
You'd create your own #DatabaseField annotation that you'd annotate the fields of the object with, specifying the corresponding Database field. You'd then, in the constructor, take your class (Class klass = this.getClass()), get the declared fields on it (klass.getDeclaredFields()), and for each of those, look at the declared annotations (field.getDeclaredAnnotations()). For each of those, if they are your custom databasefield annotation, make a note of the mapping. Once you have gone through all fields, you'll have a map of fields to database columns, which you can then go ahead and set using reflection (the Field object you have has a set method on it, you'll call that with "this" (the object being constructed) and the value you got with the result set.
Might be an interesting exercise, but I still think you'd be better off with JPA or one of the lighter weight ORMs like SimpleORM.
You can do with java reflection .
For example we will take your sql query is like this.
SELECT FirstName 'FNAME', LastName 'LNAME', Grade 'GRADE' FROM Employee
So you will get the output as the following
FNAME LNAME GRADE
John Dan A+
Then in your java code you will need to reflection to achieve the rest
Suppose your Student class is like this
public class Student {
private String LNAME;
private String FNAME;
private String GRADE;
public String getLNAME() {
return LNAME;
}
public void setLNAME(String lNAME) {
LNAME = lNAME;
}
public String getFNAME() {
return FNAME;
}
public void setFNAME(String fNAME) {
FNAME = fNAME;
}
public String getGRADE() {
return GRADE;
}
public void setGRADE(String gRADE) {
GRADE = gRADE;
} }
And you can set the corresponding values in the Student class using the following code.
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
try {
//configuring the columns in the sql statement and class
String[] ColumnArray = new String[]{"LNAME","FNAME","GRADE"};
// making a hashmap to emulate the result set of sql
HashMap<String, String> rs = new HashMap<String, String>();
rs.put("FNAME", "John");
rs.put("LNAME", "Dan");
rs.put("GRADE", "A+");
//reflection of the
Class cls = Class.forName("Student");
Object c = cls.newInstance();
Method[] mtd = cls.getMethods();
for (String column : ColumnArray) {
Method method = cls.getMethod("set"+column, String.class);
method.invoke(c, new Object[]{rs.get(column)});
}
//casting the class to employee
Student student = (Student) c;
//Printing the output
System.out.println(student.getFNAME());
System.out.println(student.getLNAME());
System.out.println(student.getGRADE());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}}
Please let me know if your facing any issue. Happy to help you.
It's not perfect but look at this:
public class Student {
private String name;
private Integer age;
//etc.
public Student() {
//default constructor
}
public Student(final ResultSet rs) throws Exception {
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
for (int i = 1; i < columnCount + 1; i++ ) {
String name = rsmd.getColumnName(i);
if (Student.getField(name)) {
Student.getField(name).set(rs.getString(name));
}
}
}
}
You should also map field to colum type, in example I used only getString.
If result of your query going to be some domain object like Student (nevermind how many joins in FROM statement) then ORM would work fine and maybe it's good solution. If you are going to extract some complex data structure then you can take a look at some Spring features like RowMapper.
You can make use of GSON serialized object mapping.
refer
Check with HIbernate SQLQuery addScalar() Example here http://www.journaldev.com/3422/hibernate-native-sql-example-addscalar-addentity-addjoin-parameter-example
This will exactly give total result-set as POJO object. You can later iterate through it for data.
Let me know if this helps you.
Assume your STUDENT table is as follows.
__________________________
|STUDENT_ID | AGE | NAME |
--------------------------
| | | |
| | | |
--------------------------
Your have to have a control over your SQL query. It's return columns must be renamed according to POJO class's variable names. So the SQL query would be like as follows.
SELECT AGE AS age, NAME AS name from STUDENT;
Finally, the POJO class's constructor is as follows. It will iterate through all the private variables inside the class, and check whether those columns are available in the ResultSet.
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.sql.ResultSet;
public class Student
{
private int age;
private String name;
public int getAge()
{
return age;
}
public void setAge( int age )
{
this.age = age;
}
public String getName()
{
return name;
}
public void setName( String name )
{
this.name = name;
}
public static void main( String[] args )
{
new Student( null );
}
public Student( ResultSet rs )
{
Field[] allFields = this.getClass().getDeclaredFields();
for ( Field field : allFields )
{
if ( Modifier.isPrivate( field.getModifiers() ) )
{
String fieldName = field.getName();
String methodName = "set" + fieldName.substring( 0, 1 ).toUpperCase() + fieldName.substring( 1 );
try
{
Method setterMethod = this.getClass().getMethod( methodName, field.getType() );
setterMethod.invoke( this, rs.getObject( fieldName ) );
}
catch ( Exception e )
{
e.printStackTrace();
}
}
}
}
}
Related
I have a current state where an enum MyType represent Type table with columns as:
ID
Name
And it's used to identify type using ID parameter with byId method:
public enum MyType {
FIRST_TYPE("First Type", 10),
SECOND_TYPE("Second Type", 20);
public static class Holder {
static Map<Integer, MyType > idMap = new HashMap<>();
private Holder() { }
}
private MyType(String name, Integer id) {
this.name = name;
this.id = id;
Holder.idMap.put(id, this);
}
public String getName() {
return name;
}
public static MyType byId(Integer id) {
return Holder.idMap.get(id);
}
My new requirement is to support also values exists in Type table, I found answers for dynamic enum, but accept answer is not to do it
No. Enums are always fixed at compile-time. The only way you could do this would be to dyamically generate the relevant bytecode.
What will be a better solution for finding also values (mainly IDs) from database (for example ID 30)
select ID from TYPE
Can I extends existing state instead of change it? can I add extra IDS from database using method?
EDIT
Even if I update as #StefanFischer suggested an interface which populate map with enum class and new database class, I still expect in code an enum return by byId method,
public interface MyType {
public static class Holder {
static Map<Integer, MyType> idMap = new HashMap<>();
private Holder() { }
}
public default void add(MyType myType, Integer id) {
Holder.idMap.put(id, myType);
}
public static MyType byId(Integer id) {
return Holder.idMap.get(id);
}
}
A distinct non-answer: you are trying to force yourself down the wrong rabbit hole.
The whole point of Enums are to give you certain advantages at compile time. At runtime, it really wouldn't matter to the JVM if you have a class with some final static Whatever fields, or an Enum with different constants. Or if you use an EnumSet versus an ordinary Set.
You use enums because they allow you to write down your source code in more elegant ways.
Therefore the approach of generating enums at runtime doesn't make sense.
The idea of enums is that you write source code using them. But when your enums are generated for you, how exactly would you write source code exploiting them?! As mentioned already, enum classes are final by default. You can't extend or enhance them separately. Whatever you would want to have, it needs to be generated for you. Which again raises the question: how would you exploit something at compile time, that gets generated at runtime?
Therefore, from a conceptual point of view, the approach outlined in the other answer (to use a Map) is a much better design point than trying to turn enums into something that they aren't meant to be.
If I understand it correctly the requirements are:
having a MyType.byId(Integer id) method that delivers some predefined values
it should be also extended dynamically from a Table Type from the database
So a enum can not be extended dynamically, but we could switch to a class.
So staying close to your code one could write something like:
import java.util.HashMap;
import java.util.Map;
public class MyType {
static Map<Integer, MyType> idMap = new HashMap<>();
static {
idMap.put(10, new MyType("First Type"));
idMap.put(20, new MyType("Second Type"));
}
private final String name;
private MyType(String name) {
this.name = name;
}
public String getName() {
return name;
}
public static MyType byId(Integer id) {
return idMap.get(id);
}
public static void addType(String name, Integer id) {
MyType lookup = byId(id);
if(lookup != null) {
if(!lookup.getName().equals(name)) {
System.out.println("conflicting redefinition for id " + id + ": '" + name + "' vs '" + lookup.name + "'");
//handle...
}
}
idMap.put(id, new MyType(name));
}
}
Test Data
Let's assume we have the following in the database:
stephan=# select * from Type;
id | name
----+-------------
30 | Third Type
10 | First Type
20 | Second Type
(3 rows)
So in the database we have the predefined types with id=10 and id=20 but also a type with id=30 that is not known per default to the application. But we can populate the types from the database.
Test Case
public static void main(String[] args) {
try {
Connection connection = createConnection();
try (connection) {
populateTypes(connection);
}
MyType type;
type = MyType.byId(10);
System.out.println(type.getName());
type = MyType.byId(20);
System.out.println(type.getName());
type = MyType.byId(30);
System.out.println(type.getName());
} catch (Exception e) {
e.printStackTrace();
}
}
JDBC Example
It doesn't matter what actual database technology is used to retrieve the values. Here an example for JDBC:
private static void populateTypes(Connection connection)
throws SQLException {
String sql = "SELECT * FROM type";
try (Statement st = connection.createStatement()) {
try (ResultSet rs = st.executeQuery(sql)) {
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
MyType.addType(name, id);
}
}
}
}
Demo Output
First Type
Second Type
Third Type
Is that what you are looking for?
enum represents a group of constants (unchangeable variables, like final variables). you can not define it on runtime.
I have an class IntegrationWithDB in which i have to method getConnection()and selectFromDB().
In the selectFromDb() i have a result set , i want to get the result
set vales in another class method
Actually it did but it only shows the last value of dataBase table.
Note i have made getter and setter method in IntegrationWithDB class and use in selectFromDB() method.
public void selectFromDB() {
try {
if (this.conn == null) {
this.getConnection();
}
if (this.stmt == null) {
this.stmt = this.conn.createStatement();
}
int success = 0;
this.query = "select * from contacts order by node_id";
this.rs = this.stmt.executeQuery(query);
// something is wrong in the while loop
while (rs.next()) {
setId(rs.getInt("node_id")); // i made getter and setter for id, name, parent and for level
setNam(rs.getString("node_name"));
setParnt(rs.getString("node_parent"));
setLvl(rs.getInt("node_parent"));
}
if (success == 0) {
this.conn.rollback();
} else {
this.conn.commit();
}
} catch (Exception ex) {
ex.printStackTrace();
}
and in another class test i have method displayList() in this method i write the following code
public class test {
IntegrationWithDbClass qaz = new IntegrationWithDbClass();
public void displayList ( ) {
qaz.getConnection();
qaz.selectFromDB();
for(int i = 0; i< 5; i++){
System.out.println(" "+qaz.getId());
System.out.println(" "+qaz.getNam());
}
}
when i initilize the displayList() method in the main method , it shows the following result
5
red
how can i get all the five values?
First of all you have to create what is commonly referred to as an Entity class. This is the class that represents a single row in your database. This should ideally be separate from the code that interacts with the database connection.
So first step, create a class named Contact, and in it put the 4 fields you have, id, name, parent and level, with the respective getter methods. If you do not expect these to change by your program make them immutable, it is the good practice to ensure consistency. So something like:
public class Contact {
private final int id;
private final String name;
private final String parent;
private final String level;
public Contact(String id, String name, String parent, String level) {
this.id = id;
this.name = name;
this.parent = parent;
this.level = level;
}
public int getId() {
return id;
}
//... put the rest of the getter methods
}
Then in your IntegrationWithDB class (I would rename this to something more meaningful like ContactRepository) you can change that method you have to:
public List<Contact> getContacts() {
// ... your database connection and query code here
this.rs = this.stmt.executeQuery(query);
List<Contact> contacts = new LinkedList<Contact>();
while (rs.next()) {
int id = rs.getInt("node_id");
String name = rs.getString("node_name");
String parent = rs.getString("node_parent");
String level = setLvl(rs.getInt("level"));
contacts.add(new Contact(id, name, parent, level));
}
//... the rest of your database handling code, don't forget to close the connection
return contacts;
}
Then from displayList() you just have to call getContacts() which gives you a list of Contact objects to iterate through.
I assume that currently you're storing those properties in int/string variables. In every iteration of the loop you're overwriting the values. What you need to do is to store them in some collection like ArrayList and in each iteration add() to this collection.
So for the below question, I tried to search online but I couldn't find the answer to it. I am working in Java language.
So I currently have a class, lets say:
public Employee(String emp_id, String location, String name)
{
this.emp_id = emp_id;
this.location = location;
this.name = name;
}
I have created multiple objects of Employee, and I have saved it in an arrayList. Now, I the user will ask which employees are located in New York, or they can ask which employees are named John.
So they can enter location New York. I need to read in the user's request, first identify what they are trying to search, and then see if there are any matching Employees in the array.
I have read in the command, and saved it in an array of strings called Search. The first index holds the name of the field/property of the object, and the second index will hold what the user actually wants to check.
String[] search = new String[] { "location", "New York" }
I was thinking for doing this:
for(Employee e: empList)
if(e.search[0].equals(search[1]))
System.out.println(e)
However, I am not able to do this, since search[0] is not a property name for the Employee object. I am getting this error: error: cannot find symbol.
Is there a way for me to access the object property without the actual name, meaning the name is saved in another String variable?
Please let me know. Appreciate your help.
Thank you.
What you are looking for is the Reflection API. Here's a simple example of how you might achieve what you need. Notice that we can query the class for its Fields and Methods. We can then do checks on Field types or Method return types. Reflection is not for the faint of heart but it can give you some extremely dynamic code.
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Employee {
public String name;
public int age;
public Employee(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
public static void main(String[] args) throws Exception {
Employee e1 = new Employee("Nick", 30);
Class<?> c = e1.getClass();
Field f = c.getField("name");
System.out.print("Type: ");
System.out.println(f.getType());
System.out.print("Object: ");
System.out.println(f.get(e1));
System.out.println();
System.out.println("Methods: ");
Method[] methods = c.getMethods();
for(int i = 0; i < methods.length; i++) {
System.out.print("Name: ");
System.out.println(methods[i].getName());
System.out.print("Return type: ");
System.out.println(methods[i].getReturnType());
// imagine this value was set by user input
String property = "name";
if( methods[i].getName().toLowerCase().equals("get" + property) ) {
System.out.print("Value of " + property + " is: ");
System.out.println(methods[i].invoke(e1));
}
}
}
}
You could write your class to allow querying in this way, by wrapping a Map (or a Properties if you prefer:
public class Employee {
private Map<String,String> properties = new HashMap<>();
public Employee(String emp_id, String location, String name) {
properties.put("emp_id", empt_id);
properties.put("location", location);
properties.put("name", name);
}
public String getProperty(String key) {
return properties.get(key);
}
}
You can expose the fields as getters if you like:
public String getName() {
return this.getProperty("name");
}
The opposite way around, of course, is to explicitly write a getProperty(String) to access fields:
public String getProperty(String key) {
switch(key) {
case "name":
return this.name;
case "empId":
return this.empId;
case "location":
return this.location;
default:
throw new NoSuchFieldException; // or return null, or whatever
}
}
This may seem long-winded, but it's pretty easy and effective.
You can also use Reflection to work with the class at runtime. This is not recommended for new programmers - not because it is difficult as such, but because usually there's a cleaner way. And it subverts Java's access control features (e.g. it can read private fields).
Reflection includes techniques such as Class<?> c = e1.getClass(); Field f = c.getField("name"); -- there are no checks at compile time that e1 has a field called name. It will only fail at runtime.
If you're willing to use the Bean method naming conventions -- mostly simply that getName() is an accessor for a field called name -- then you could use Apache BeanUtils to work with the object. This is also Reflection, but it's wrapped in a more task-centric API.
String name = PropertyUtils.getProperty("name");
... this will:
call getName() and return the result, if getName() exists
throw NoSuchMethodException if there is no getName() method
other exceptions for other failures (see the JavaDoc)
So you could write:
public boolean isMatch(Employee employee, String[] search) {
String key = search[0];
String expectedValue = search[1];
try {
String actual = PropertyUtils.getProperty(key);
return(Objects.equals(actual,expected)); // Objects.equals is null-safe
} catch (NoSuchMethodException e) {
return false;
}
}
This is just pseudocode. But here you are getting each Employee object at index i and getting the name returned in the form of a string from this employee at index i.
for (int i = 0; i < empList.size(); i++)
{
if (empList.get(i).getId().equals(search[1]) || empList.get(i).getName().equals(search[1]) || empList.get(i).getLocation().equals(search[1]))
return true;
}
So basically, iterate through your list of objects Employee. At each employee, getName() returns the string value of the name of this Employee.
That is how you access the properties, with your getter method.
public String getName()
{
return this.name;
}
You can use the getFields() method if the Class, although I recommend you a simpler method if the class have so little properties, you can just use the or operation to achieve this:
for(Employee e: empList)
if(e.getLocation().equals(Search[1])||e.getName().equals(Search[1]))
System.out.println(e)
Using the getFields() method:
String searchValue="The string you have to search";
for(Employee e: empList){
List<Field> selectedFields=new ArrayList<Field>();
for (int i = 0; i < e.getClass().getFields().length; i++) {
if(e.getClass().getFields()[i].getType().getName().equals("String")){
selectedFields.add(e.getClass().getFields()[i]);
}
}
for(Field f:selectedFields){
if(f.get(e).equals(searchValue)){
System.out.println(e);
}
}
}
}
As mentioned in other answers: this can be solved with reflection. Another approach with some java8-sugar:
public static void main(String[] args) {
List<Employee> unfilteredList = new ArrayList<>();
// ... Add the employees
String[] fieldAndExpectedValue = new String[] { "location", "Narnia-City" };
List<Employee> filteredList = unfilteredList.stream().filter(
employee -> objectHasFieldWithValue(employee, fieldAndExpectedValue[0], fieldAndExpectedValue[1]))
.collect(Collectors.toList());
// ...
}
private static <INSTANCE, FIELDVALUE> boolean objectHasFieldWithValue(INSTANCE o,
String fieldName, FIELDVALUE expectedValue) {
try {
Field f = o.getClass().getDeclaredField(fieldName);
f.setAccessible(true);
if (f.getType().isInstance(expectedValue) && expectedValue.equals(f.get(o))) {
return true;
}
} catch (Exception exc) {
exc.printStackTrace();
}
return false;
}
It's weird that all the answers focus on reflection. Design wise, you should be using getters to solve your problem. It is true that you need to use reflection to retrieve a property without any extra logic in that section of code, but your problem should rely on improving the searching logic rather than exposing fields and breaking SOLID OOP design.
From the looks of it you want a simple solution for searching through an array of objects and checking if the a property matches a certain value.
This would be an answer to that question:
///public class Employee {
public bool doesEmployeeMatch(String property, String value){
switch(property){
case "location": return value.equals(this.location);
break;
case "name": return value.equals(this.name);
break;
default: System.out.println("Invalid parameter");
break;
}
}
///where ever you're searching through empList
for(Employee e: empList)
if(e.doesEmployeeMatch(search[0],search[1])){
System.out.println(e);
break;
}
But that isn't how the question should be formed. Best way of forming the question would be "I need to determine the search parameter, then find the Employees that match the value of my parameter." That means you should have two steps to logically handle this actions. First figure out what field you want to find, then find all the employees that have the expected value on said field.
So what would that look like?
First you'll need some getter functions.
public class Employee {
private String emp_id, location, name;
public Employee(String emp_id, String location, String name) {
this.emp_id = emp_id;
this.location = location;
this.name = name;
}
public String getEmp_id(){
return this.emp_id;
}
public String getLocation(){
return this.location;
}
public String getName(){
return this.Name;
}
}
Next up you need to add logic for determining which getter to use.
///sorry I just threw a method name out for you
public bool findEmployeeMatch(String[] search){
switch(search[0]){
case "location":
break;
case "name":
break;
default:
break;
}
Finally add some lambda expressions to impress the masses.
public bool findEmployeeMatch(String[] search, empList){
///other code maybe?
switch(search[0]){
case "location": Arrays.stream(empList).forEach(e)->
if(e.getLocation().equals(search[1])){
System.out.println(e);
}
break;
case "name": Arrays.stream(empList).forEach(e)->
if(e.getName().equals(search[1])){
System.out.println(e);
}
break;
case "emp_id": Arrays.stream(empList).forEach(e)->
if(e.getEmp_List().equals(search[1])){
System.out.println(e);
}
break;
default: System.out.println("Invalid parameter");
break;
}
I can't see why there would be a reason to not check for what field they would want, as using reflection is costly and seeing how this is an app that expects users to search for data in a backend, whether for work or school, I do not believe reflection is the thing you want to be using.
I suggest not to use reflection API at all. It is messy and not type safe.
Instead use Functional interface Java 8 provides or similar constructs if you are not using Java 8. Here is a cleaner type safe solution using Java 8:
public class Search<T> {
private T searchValue = null;
private Function<Employee, T> getter = null;
public Search(T searchValue, Function<Employee, T> getter) {
this.searchValue = searchValue;
this.getter = getter;
}
public T getSearchValue() {
return searchValue;
}
public void setSearchValue(T searchValue) {
this.searchValue = searchValue;
}
public Function<Employee, T> getGetter() {
return getter;
}
public void setGetter(Function<Employee, T> getter) {
this.getter = getter;
}
}
public Optional<Employee> find(List<Employee> empList, Search<?> search){
for (Employee e : empList){
if ( Objects.equals( search.getGetter().apply(e), search.getSearchValue() ) ) return Optional.of(e);
}
return Optional.empty();
}
And you can search like this:
find( empList, new Search<>("Mark", Employee::getName ) ) //finds Employee with name Mark
find( empList, new Search<>("Toronto", Employee::getLocation ) ) //finds Employee with location in Toronto
Update:
Here is method that maps user specified field name to actual Search:
public static Search<String> create(String searchValue, String fieldName){
if ( "name".equalsIgnoreCase(fieldName) ) return new Search<>(searchValue, Employee::getName );
else if ( "location".equalsIgnoreCase(fieldName) ) return new Search<>(searchValue, Employee::getLocation );
else throw new IllegalArgumentException("Unsupported fieldName: " + fieldName);
}
find(empList, Search.create("Toronto", "location" ) )
Im try to insert data into Database using ArrayList.there is a Erro msg.
That is my Custmer.class method. this is what i got from when i going to pass ArrayList into another class.
incompatible types: ArrayList<String> cannot be converted to ArrayList<Inquiries>
I want to know how to do this using correct Using OOP concept
public void passingMsg(ArrayList<Inquiries> arrlist){
try {
System.out.println("Method "+arrlist);
String sq = "INSERT INTO Inquiries (name,mail,tp,msg)VALUES(?,?,?)";
PreparedStatement pr = con.prepareStatement(sq);
for(int i=0;i<arrlist.size();i++){
pr.setString(1,arrlist.get(i).getName());
pr.setString(2,arrlist.get(i).getMail());
pr.setString(3,arrlist.get(i).getTp());
pr.setString(4,arrlist.get(i).getMsg());
}
pr.executeQuery();//executeBatch();
} catch (SQLException ex) {
}
}
and this is how i get values from user
String name = txtName.getText();
String mail = txtEmail.getText();
String tp = txtTp.getText();
String msg = txtMsg.getText();
ArrayList<String> arrInq = new ArrayList<String>();
arrInq.add(name);
arrInq.add(mail);
arrInq.add(tp);
arrInq.add(msg);
Custmer c =new Custmer();
if( c.passingMsg(arrInq)){
try {
JOptionPane.showMessageDialog(this, "Successs!!");
} catch (Exception e) {
JOptionPane.showMessageDialog(this, "Unsuccesss!!");
e.printStackTrace();
}
}
and this is my Inquiries.class :
public class Inquiries {
private String name;
private String mail;
private String tp;
private String msg;
public Inquiries(String name,String mail,String tp,String msg){
this.name = name;
this.mail = mail;
this.tp = tp;
this.msg = msg;
}
//
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMail() {
return mail;
}
public void setMail(String mail) {
this.mail = mail;
}
public String getTp() {
return tp;
}
public void setTp(String tp) {
this.tp = tp;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
Can Some one please explain whats wrong with this. please ?
Reason For Error
This was simply telling you that your types were incompatible for the operation you were trying to perform. In your passingMsg() method, you have its header as: public void passingMsg(ArrayList<Inquiries> arrlist). However, inside your "how i get values from user" area, which I will now refer to as "2nd Snippet", you have your method call declared as: if( c.passingMsg(arrInq)). This means that you are implying that your parameter being passed, arrInq in this case, is of the type ArrayList<Inquiries>, but it's not. It's being initialized in your 2nd Snippet as: ArrayList<String> arrInq = new ArrayList<String>();
Simple Fix
I take no responsibility for this code; use at your own risk. To fix this, you would want to change that entire 2nd Snippet to something similar to the following:
String name = txtName.getText();
String mail = txtEmail.getText();
String tp = txtTp.getText();
String msg = txtMsg.getText();
ArrayList<Inquiries> arrInq = new ArrayList<Inquiries>();
arrInq.add(new Inquiries(name, mail, tp, msg));
Custmer c = new Custmer();
try {
c.passingMsg(arrInq);
JOptionPane.showMessageDialog(this, "Successs!!");
} catch (Exception e) {
JOptionPane.showMessageDialog(this, "Unsuccesss!!");
e.printStackTrace();
}
You would also want to change the method header to either return a boolean, or fix it up a little bit to actually throw the exception. Such as:
public void passingMsg(ArrayList<Inquiries> arrlist) {
System.out.println("Method " + arrlist);
String sq = "INSERT INTO Inquiries(name,mail,tp,msg) VALUES(?,?,?)";
PreparedStatement pr = con.prepareStatement(sq);
for (Inquiries inquiries : arrlist) {
pr.setString(1, inquiries.getName());
pr.setString(2, inquiries.getMail());
pr.setString(3, inquiries.getTp());
pr.setString(4, inquiries.getMsg());
}
pr.executeQuery();//executeBatch();
}
Let's talk in O-O-P way.
Here Inquiries is your model, model is nothing but simple class that has instance members and public methods to get and set value of model's instance variable.
Generally we put all database related operations code in their respective models.
e.g. I have model "Model" which typically maps to database table say it as "TableModel" ,I would do something like this:
public class Model{
private int id;
private String attr;
//other properties of the model
public int getId(){
return id;
}
public void setId(int id){
this.id=id;
}
//other getters and setters
//here we write methods to performs database operations
public void save(){
//use "this" to get properties of object
//logic to save to this object in database table TableModel as record
}
public void delete(int id){
//logic to delete this object i.e. from database table TableModel
}
public Model get(int id){
//retrieve record from table TableModel with this id
}
//other methods to get data from database.
}
Now question is how I can use this in some another class. Let's say I have list of Model objects and I wish to insert them in to database.I will do it something like this:
public class AnotherClass{
public void someMethod(){
//create list of models objects e.g. get them from user interface
ArrayList<Model> models=new ArrayList<>();
for(int i=0;i<3;i++){
Model model=new Model();
model.setId(i);
model.setAttr("attr"+i);
models.add(model);
}
SomeOtherClass obj=new SomeOtherClass();
obj.insert(models);
}
}
public class SomeOtherClass{
//other code above.....
//my method that inserts each Model object in database
//Note: this is sample method , you should do it in optimized way
// e.g. batch insert
public void insert(ArrayList<Model> models){
for(Model myModel:models){
myModel.save();
}
}
//other code below.....
}
You are using the wrong type parameter for the ArrayList. Instead of ArrayList<String> you need ArrayList<Inquiries>. To fix the problem, you should remove this code ...
ArrayList<String> arrInq = new ArrayList<String>();
arrInq.add(name);
arrInq.add(mail);
arrInq.add(tp);
arrInq.add(msg);
... and replace it with this code:
ArrayList<Inquiries> arrInq = new ArrayList<Inquiries>();
arrInq.add(new Inquiries(name, mail, tp, msg));
I was using multiple constructor from the same class, but a few days ago I got a 'rare' problem. The constructor initializes all the fields =(
I have Ejercicio.java class
public class Ejercicios {
int Id_Ejercicio;
String Descripcion;
String Finalidad;
String Duracion;
//Constructor
public Ejercicios() {
super();
}
//Constructor with 2 fields
public Ejercicios(int id_Ejercicio, String descripcion) {
super();
Id_Ejercicio = id_Ejercicio;
Descripcion = descripcion;
}
//Constructor with 4 fields
public Ejercicios(int id_Ejercicio, String descripcion, String finalidad, String duracion) {
super();
Id_Ejercicio = id_Ejercicio;
Descripcion = descripcion;
Finalidad = finalidad;
Duracion = duracion;
}
}
And the Lista_Ejercicios.java class
public class List_Ejercicios {
ArrayList<Ejercicios> lejer;
public List_Ejercicios() {
super();
}
}
And my principal class where I try to use these differents constructors
public Response Principal(SQLQuery){
List<Ejercicios> listaEJER = new ArrayList<Ejercicios>();
dbCon = new ConexionBD();
ResultSet rslt;
try {
conn = (Connection) ConexionBD.setDBConnection();
rslt = dbCon.getResultSet(SQLQuery, conn);
while(rslt.next()){
listaEJER.add(new Ejercicios( rslt.getInt(1),rslt.getString(2) ));
}
}catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//finally block code
return Response.ok(listaEJER.toArray()).build();
}
I was using 'Advanced Rest Client' for Chrome and I don't have an idea why I receive the 4 fields instead 2 like I especified in the constructor
...
{
descripcion: "Jump as high as you can"
id_Ejercicio: 1
finalidad: null
duracion: null
}
...
I have in trouble, these constructors work two weeks ago I don't have any clue why currently its running doesn't work.
They did not work two weeks ago. You've changed something. When you declare a field in your class, that field is always there. If you don't initialise it in your constructor, it will be auto-initialised. For classes, this default value is null, whereas for primitives it is 0, false etc. However, this behaves exactly the same as if you had initialised it to that value in the constructor - myEjercicios.Finalidad (use naming conventions please) will be null, as it is an auto-initialised object of type String.
As for fixing this issue, it shouldn't be hard to write some code to not print values that are null. If you want a different set of fields, however, you must declare two different classes (perhaps one extending the other).