Tuesday, July 16, 2024

Node.js MySQL Select Statement Example

In this post we'll see examples of Select statement using Node.js and MySQL to fetch data from DB. We'll be using the Promise Based API provided by MySQL2 library and a connection pool to connect to database in the examples provided here.

Refer Node.js - MySQL Connection Pool to get more information about using MySQL Connection Pool with Node.js

Table used

Table used for the example is Employee table with columns as- id, name, age, join_date.


CREATE TABLE `node`.`employee` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(45) NULL,
  `join_date` DATE NOT NULL,
  `age` INT NULL,
  PRIMARY KEY (`id`));

Id is auto incremented so we don't need to send that data from our code.

Node.js MySQL Select statement example

In this example all the records are fetched from the Employee table.

We'll keep the DB connection configuration in a separate file that can be used wherever it is needed by importing it.

util\database.js

const mysql = require('mysql2/promise');

const pool = mysql.createPool({
    host: 'localhost',
    user: 'root',
    password: 'admin',
    database: 'node',
    waitForConnections: true, 
    connectionLimit: 10,
  });

module.exports = pool;

As you can see pool object is exported here so that it can be used in other files.

app.js

In this file let's create a function to select all the records from the Employee table.

const pool = require('./util/database');

async function getEmployees(){
  const sql = "SELECT * FROM EMPLOYEE";
  try{
    const conn = await pool.getConnection();
    const [results, fields] = await conn.query(sql);
    console.log(results); // results contains rows returned by server
    console.log(fields);
    conn.release();
  }catch(err){
    console.log(err);
  }
}

getEmployees(30);

Important points to note here-

  1. getEmployees () function is a async function as we are using async/await (Promise based API) rather than callback based API.
  2. We are using await with pool.getConnection() method.
  3. By using array destructuring we get the returned values for results and fields.
  4. results contains rows returned by server.
  5. fields variable contains extra meta data about results, if available.
  6. After the task, connection is released using conn.release() which means connection goes back to the pool.

On running the file-

>node app.js
[
  {
    id: 1,
    name: 'Ishan',
    join_date: 2024-03-23T18:30:00.000Z,
    age: 28
  },
  {
    id: 2,
    name: 'Rajesh',
    join_date: 2023-06-16T18:30:00.000Z,
    age: 34
  }
]
[
  `id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
  `name` VARCHAR(45),
  `join_date` DATE(10) NOT NULL,
  `age` INT
]

Select with where condition example

In this example we'll have a condition using Where clause, only those records are selected that fulfil the condition. For the condition, parameterized query is used.

app.js

In this file let's create a function to select data from the Employee table in MySQL based on the age condition.

const pool = require('./util/database');

async function getEmployeesByAge(age){
  const sql = "SELECT * FROM EMPLOYEE where age >?";
  const values = [age];
  try{
    const conn = await pool.getConnection();
    const [result, fields] = await conn.execute(sql, values);
    console.log(result); // results contains rows returned by server
    console.log(fields); // fields contains extra meta data about results, if available
    conn.release(); // connection sent back to pool
  }catch(err){
    console.log(err);
  }
}

getEmployeesByAge(30);

On running it

>node app.js
[
  {
    id: 2,
    name: 'Rajesh',
    join_date: 2023-06-16T18:30:00.000Z,
    age: 34
  }
]
[
  `id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
  `name` VARCHAR(45),
  `join_date` DATE(10) NOT NULL,
  `age` INT
]

That's all for this topic Node.js MySQL Select Statement Example. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Node.js MySQL Insert Example
  2. Node.js - Connect to MySQL Promise API

You may also like-

  1. How to Setup a Node.js Project
  2. Node.js Event Driven Architecture
  3. Node.js path.basename() Method With Examples
  4. Writing a File in Node.js
  5. Fail-Fast Vs Fail-Safe Iterator in Java
  6. Java Stream - Convert Stream to List
  7. Switch Expressions in Java 12
  8. Custom Pipe in Angular With Example

Monday, July 15, 2024

Node.js MySQL Insert Example

In this post we'll see examples of inserting records into table using Node.js and MySQL. We'll be using the Promise Based API provided by MySQL2 library and a connection pool to connect to database in the examples provided here.

Refer Node.js - MySQL Connection Pool to get more information about using MySQL Connection Pool with Node.js

Table used

Table used for the example is Employee table with columns as- id, name, age, join_date.


CREATE TABLE `node`.`employee` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(45) NULL,
  `join_date` DATE NOT NULL,
  `age` INT NULL,
  PRIMARY KEY (`id`));

Id is auto incremented so we don't need to send that data from our code.

Node.js insert record MySQL example

We'll keep the DB connection configuration in a separate file that can be used wherever it is needed by importing it.

util\database.js

const mysql = require('mysql2/promise');

const pool = mysql.createPool({
    host: 'localhost',
    user: 'root',
    password: 'admin',
    database: 'node',
    waitForConnections: true, 
    connectionLimit: 10,
  });

module.exports = pool;

As you can see pool object is exported here so that it can be used in other files.

app.js

In this file let's create a function to insert data into the Employee table in MySQL.

const pool = require('./util/database');

async function insertEmployee(){
  const sql = "INSERT INTO EMPLOYEE (name, join_date, age) values ('Ishan', '2023-11-22', 31)";
  try{
    const conn = await pool.getConnection();
    const [result, fields] = await conn.query(sql);
    console.log(result);
    console.log(fields);
    conn.release();
  }catch(err){
    console.log(err);
  }
}

// call the function
insertEmployee();

Important points to note here-

  • insertEmployee() function is a async function as we are using async/await (Promise based API) rather than callback based API.
  • We are using await with pool.getConnection() method.
  • By using array destructuring we get the returned values for result and fields.
  • fields variable contains extra meta data about results, if available.
  • result contains a ResultSetHeader object, which provides details about the operation executed by the server.
  • After the task, connection is released using conn.release() which means connection goes back to the pool.

On running the file-

>node app.js

ResultSetHeader {
  fieldCount: 0,
  affectedRows: 1,
  insertId: 1,
  info: '',
  serverStatus: 2,
  warningStatus: 0,
  changedRows: 0
}
Undefined

If you want to get the number of rows inserted you can get it using result.affectedRows and to get the id of the inserted row you can use result.insertId

Using parameterized Insert query

In the above example problem is that insert query will insert the same record as the data is hardcoded. To make it more generic you can use a parameterized query with the placeholders for the values that are passed later.

const pool = require('./util/database');

async function insertEmployee(empName, joinDate, age){
  const sql = "INSERT INTO EMPLOYEE (name, join_date, age) values (?, ?, ?)";
  const values = [empName, joinDate, age];
  try{
    const conn = await pool.getConnection();
    const [result, fields] = await conn.execute(sql, values);
    console.log(result);
    console.log(fields);
    conn.release();
  }catch(err){
    console.log(err);
  }
}

// call the function
insertEmployee('Ishan', '2024-03-24', 28);
insertEmployee('Rajesh', '2023-06-17', 34);

Important points to note here-

  1. Prepared statement is used now where placeholders are used to pass values later.
  2. Values are passed in an array which is also passed along with the query.
  3. conn.execute() is used here rather than conn.query() as execute helper prepares and queries the statement.

Inserting multiple records - Node.js and MySQL

In the above example parameterized query is used which is definitely a step forward to using hardcoded data. If you have multiple records to be inserted simultaneously then you can use single question mark '?' which represents multiple rows of data coming from an array.

app.js

const pool = require('./util/database');

async function insertEmployee(data){
  const sql = "INSERT INTO EMPLOYEE (name, join_date, age) values ?";
  
  try{
    const conn = await pool.getConnection();
    const [result, fields] = await conn.query(sql, [data]);
    console.log(result);
    console.log(fields);
    conn.release();
  }catch(err){
    console.log(err);
  }
}

const records = [
  ['Ishan', '2024-03-24', 28], 
  ['Rajesh', '2023-06-17', 34]
]
// call the function
insertEmployee(records);

On running it

>node app.js

ResultSetHeader {
  fieldCount: 0,
  affectedRows: 2,
  insertId: 1,
  info: 'Records: 2  Duplicates: 0  Warnings: 0',
  serverStatus: 2,
  warningStatus: 0,
  changedRows: 0
}

Undefined

As you can see affected rows count is 2.

That's all for this topic Node.js MySQL Insert Example. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Node.js - How to Connect to MySQL
  2. Node.js MySQL Select Statement Example

You may also like-

  1. Difference Between __dirname and process.cwd() in Node.js
  2. Node.js path.join() Method
  3. Reading a File in Node.js
  4. Setting Wild Card Route in Angular
  5. Difference Between Comparable and Comparator in Java
  6. Java is a Strongly Typed Language
  7. How to Create Password Protected Zip File in Java

Monday, July 8, 2024

How ArrayList Works Internally in Java

ArrayList arguably would be the most used collection along with the HashMap. Many of us programmers whip up code everyday which contains atleast one of these data structures to hold objects. I have already discussed how HashMap works internally in Java, in this post I'll try to explain how ArrayList internally works in Java.

As most of us would already be knowing that ArrayList is a Resizable-array implementation of the List interface i.e. ArrayList grows dynamically as the elements are added to it. So let's try to get clear idea about the following points-

  • How ArrayList is internally implemented in Java.
  • What is the backing data structure for an ArrayList.
  • How it grows dynamically and ensures that there is always room to add elements.

Because of all these side questions it is also a very important Java Collections interview question.

Note that the code of ArrayList used here for reference is from Java 17


Where does ArrayList internally store elements

Basic data structure used by Java ArrayList to store objects is an array of Object class, which is defined as follows-

transient Object[] elementData;

I am sure many of you would be thinking why transient and how about serializing an ArrayList then?
ArrayList provides its own version of readObject and writeObject methods so no problem in serializing an ArrayList and that is the reason, I think, of making this Object array as transient.

Sunday, July 7, 2024

ArrayList in Java With Examples

Java ArrayList is one of the most used collection and most of its usefulness comes from the fact that it grows dynamically. Contrary to arrays you don't have to anticipate in advance how many elements you are going to store in the ArrayList. As and when elements are added ArrayList keeps growing, if required.

Though internally it is not really some "elastic" array which keeps growing, it is as simple as having an array with an initial capacity (default is array of length 10). When that limit is crossed another array is created which is 1.5 times the original array and the elements from the old array are copied to the new array.

Refer How does ArrayList work internally in Java to know more about how does ArrayList work internally in Java.


Hierarchy of the ArrayList

To know the hierarchy of java.util.ArrayList you need to know about 2 interfaces and 2 abstract classes.

  • Collection Interface- Collection interface is the core of the Collection Framework. It must be implemented by any class that defines a collection.
  • List interface- List interface extends Collection interface. Apart from extending all the methods of the Collection interface, List interface defines some methods of its own.
  • AbstractCollection- Abstract class which implements most of the methods of the Collection interface.
  • AbstractList- Abstract class which extends AbstractCollection and implements most of the List interface.

ArrayList extends AbstractList and implements List interface too. Apart from List interface, ArrayList also implements RandomAccess, Cloneable, java.io.Serializable interfaces.

Saturday, July 6, 2024

Spring MVC - Binding List of Objects Example

In this post we’ll see how to bind a list of objects in Spring MVC so that the objects in that List can be displayed in the view part or to add to an ArrayList by binding object properties in view.

Spring MVC Project structure using Maven


Maven Dependencies

This example uses Spring 6 which uses Jakarta EE 9+ (in the jakarta namespace). JSTL tags are also used in this Spring MVC example for binding list of objects so you need to add Maven dependency for JSTL apart from Spring dependencies. Here only properties and dependencies section is given.

<properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <maven.compiler.source>17</maven.compiler.source>
  <maven.compiler.target>17</maven.compiler.target>
  <spring.version>6.1.10</spring.version>
</properties>

<dependencies>
    <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-core</artifactId>
     <version>${spring.version}</version>
  </dependency>
  <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
  </dependency>
  <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
  </dependency>
  <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
  </dependency>
<!-- https://mvnrepository.com/artifact/jakarta.servlet.jsp.jstl/jakarta.servlet.jsp.jstl-api -->
<dependency>
    <groupId>jakarta.servlet.jsp.jstl</groupId>
    <artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
    <version>3.0.0</version>
</dependency>
<dependency>
    <groupId>org.glassfish.web</groupId>
    <artifactId>jakarta.servlet.jsp.jstl</artifactId>
    <version>3.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/jstl/jstl -->
<dependency>
    <groupId>jstl</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>

  <!--<dependency>
     <groupId>taglibs</groupId>
     <artifactId>standard</artifactId>
     <version>1.1.2</version>
</dependency>-->
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
  </dependency>
  
</dependencies>

Spring MVC binding List example – Required XML Configuration

Since JSTL tags are used in JSP so you need your view to resolve to JstlView, for that you need to add viewClass property in the bean definition for InternalResourceViewResolver in your DispatcherServlet configuration.

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
  <property name="prefix" value="/WEB-INF/jsp/" />
  <property name="suffix" value=".jsp" />
</bean>

Spring MVC binding List example – Model classes

List stores objects of the User class which is defined as given below.

public class User {

 private String firstName;
 private String lastName;
 private String email;
 public User() {}
 public User(String firstName, String lastName, String email) {
  this.firstName = firstName;
  this.lastName = lastName;
  this.email = email;
 }
 
 public String getFirstName() {
  return firstName;
 }
 public void setFirstName(String firstName) {
  this.firstName = firstName;
 }
 public String getLastName() {
  return lastName;
 }
 public void setLastName(String lastName) {
  this.lastName = lastName;
 }
 public String getEmail() {
  return email;
 }
 public void setEmail(String email) {
  this.email = email;
 }
}

Following class acts a container for the List of User objects.

public class UserListContainer {
  private List<User> users;

  public List<User> getUsers() {
    return users;
  }

  public void setUsers(List<User> users) {
    this.users = users;
  }
}

Spring MVC binding List example – Controller class

@Controller
public class UserController {
  @RequestMapping(value = "/getUsers", method = RequestMethod.GET)
  public String getUsers(Model model) throws Exception{
    List<User> users = getListOfUsers();
    UserListContainer userList = new UserListContainer();
    userList.setUsers(users);
    model.addAttribute("Users", userList);
    return "showUsers";
  }
    
  // Dummy method for adding List of Users
  private List<User> getListOfUsers() {
    List<User> users = new ArrayList<User>();
    users.add(new User("Jack", "Reacher", "abc@xyz.com"));
    users.add(new User("Remington", "Steele", "rs@cbd.com"));
    users.add(new User("Jonathan", "Raven", "jr@sn.com"));
    return users;
  }    
}

In the controller class there is a handler method getUsers() where a list of users is created and set to the UserListContainer which in turn is added as an attribute to the Model. Logical view name returned from the method is showUsers which resolves to a JSP at the location WEB-INF\jsp\showUsers.jsp.

Spring MVC binding List example – Views

If you just want to iterate the list and show the object fields then you can use the given JSP.

WEB-INF\jsp\showUsers.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Spring MVC List of objects display</title>
</head>
<body>
<table>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
</tr>
<c:forEach items="${Users.users}" var="user" varStatus="tagStatus">
  <tr>
    <td>${user.firstName}</td>
    <td>${user.lastName}</td>
    <td>${user.email}</td>
  </tr>
</c:forEach>
</table>
</body>
</html>

Here JSTL Core <c:forEach> tag is used to iterate over a collection of objects. Using var attribute you can provide a variable to point to the current item in the collection, which is "user" in the code.

Just showing the object fields

Binding list of objects

If you want to iterate the list, show the object fields and want to bind the List of objects again to modelAttribute then you can use the following JSP. The JSP displays a form with input boxes mapping to each object property. Form gives the functionality to update email of the user.

WEB-INF\jsp\updateUsers.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Spring MVC List of objects display</title>
</head>
<body>
<form:form method="POST" action="saveUsers" modelAttribute="Users">
<table>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
</tr>
<c:forEach items="${Users.users}" var="user" varStatus="tagStatus">
    <tr>
        <td><form:input path="users[${tagStatus.index}].firstName" value="${user.firstName}" readonly="true" /></td>
        <td><form:input path="users[${tagStatus.index}].lastName" value="${user.lastName}" readonly="true" /></td>
        <td><form:input path="users[${tagStatus.index}].email" value="${user.email}" /></td>
    </tr>
</c:forEach>
</table>
<input type="submit" value="Save" />
</form:form>
</body>
</html>

Important points to note here

  1. In this JSP Spring form tags are used for Spring MVC form fields and for looping the List JSTL tag is used. For these tag libraries following lines are added in the JSP.
    <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
    <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
    
  2. Using varStatus attribute you can get the current index (loop status). Index is 0 based.
  3. Path attribute in form tag is the path to property for data binding. For example, in the first iteration of the loop, because of providing this path attribute, input element will translate to.
      
    <tr>
      <td><input id="users0.firstName" name="users[0].firstName" value="Jack" readonly="readonly" type="text" /></td>
      <td><input id="users0.lastName" name="users[0].lastName" value="Reacher" readonly="readonly" type="text" /></td>
      <td><input id="users0.email" name="users[0].email" value="abc@xyz.com" type="text" /></td>
    </tr>
    
    As you can see what is displayed in the input boxes maps to properties of the first User object in the List.

You need to change the UserController class to test this.

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.netjstech.springweb.model.User;
import com.netjstech.springweb.model.UserListContainer;

@Controller
public class UserController {
  @RequestMapping(value = "/getUsers", method = RequestMethod.GET)
  public String getUsers(Model model) throws Exception{
    List<User> users = getListOfUsers();
    UserListContainer userList = new UserListContainer();
    userList.setUsers(users);
    model.addAttribute("Users", userList);
    return "updateUsers";
  }
    
  // Dummy method for adding List of Users
  private List<User> getListOfUsers() {
    List<User> users = new ArrayList<User>();
    users.add(new User("Jack", "Reacher", "abc@xyz.com"));
    users.add(new User("Remington", "Steele", "rs@cbd.com"));
    users.add(new User("Jonathan", "Raven", "jr@sn.com"));
    return users;
  } 
  
  @RequestMapping(value = "/saveUsers", method = RequestMethod.POST)
  public String saveUsers(@ModelAttribute("Users") UserListContainer userList) throws Exception{
    List<User> users = userList.getUsers();
    for(User user : users) {
      System.out.println("Email- " + user.getEmail());
    }
    return "updateUsers";
  }
}

Once the application is deployed it can be accessed using the URL - http://localhost:8080/spring-mvc/getUsers which now resolves to updatedUsers.jsp view.

Showing the object fields and binding to Model

Binding list of objects Spring MVC

From the above image you can notice that email for two of the users is updated. On clicking save you can check in the console also to verify that the user object properties are actually updating.

Email- jack@xyz.com
Email- remingtons@cbd.com
Email- jr@sn.com
  

That's all for this topic Spring MVC - Binding List of Objects Example. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Spring Tutorial Page


Related Topics

  1. Spring MVC File Download Example
  2. Spring MVC Exception Handling Example Using @ExceptionHandler And @ControllerAdvice
  3. Difference Between @Controller And @RestController Annotations in Spring
  4. Spring MVC Dot (.) Truncation Problem With @PathVariable Annotation
  5. Spring JdbcTemplate Insert, Update And Delete Example

You may also like-

  1. Spring Batch Processing With List of Objects in batchUpdate() Method
  2. registerShutdownHook() Method in Spring Framework
  3. ApplicationContextAware And BeanNameAware Interfaces in Spring Framework
  4. Autowiring Using Annotations in Spring
  5. Java Stream API Interview Questions And Answers
  6. Difference Between ArrayList And CopyOnWriteArrayList in Java
  7. Multiple Catch Blocks in Java Exception Handling
  8. Uber Mode in Hadoop

Thursday, July 4, 2024

Node.js - MySQL Connection Pool

In the post Node.js - Connect to MySQL Promise API we have seen how to connect to MySQL using Promise based API of mysql2 package. Using mysql2 package you can also create a connection pool.

By using a database connection pool, you can create a pool of connections that can be reused, that helps in reducing the time spent connecting to the MySQL server. When you need to connect to DB you take a connection from the pool and that connection is released again to the pool, rather than closing it, when you are done.

Creating MySQl connection pool

You can create a connection pool by using createPool() method.

import mysql from 'mysql2/promise';
const pool = mysql.createPool({
  host: 'localhost',
  user: 'USER_NAME',
  password: 'PASSWORD',
  database: 'node', 
  port: 3306
});

Replace USER_NAME and PASSWORD with your MySQL configured user name and password. Port number used is the default 3306 (if you are using default port even port number is optional) and it is connecting to DB named node which I have created in MySQL.

There are other settings also for which default is used if no value is provided.

import mysql from 'mysql2/promise';

const pool = mysql.createPool({
  host: 'localhost',
  user: 'root',
  database: 'test',
  waitForConnections: true,
  connectionLimit: 10,
  maxIdle: 10, // max idle connections, the default value is the same as `connectionLimit`
  idleTimeout: 60000, // idle connections timeout, in milliseconds, the default value 60000
  queueLimit: 0,
  enableKeepAlive: true,
  keepAliveInitialDelay: 0,
});

MYSQL2 Connection Pool with Promise Based API Example

Here is a complete example where connection pool is used to get a connection and execute queries.

Table used for the example-

CREATE TABLE `node`.`employee` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(45) NULL,
  `join_date` DATE NOT NULL,
  `age` INT NULL,
  PRIMARY KEY (`id`));

util\database.js

This is the file where connection pool is created and pool object is exported so that it can be used in other files.

const mysql = require('mysql2/promise');

const pool = mysql.createPool({
  host: 'localhost',
  user: 'root',
  password: 'admin',
  database: 'node',
  waitForConnections: true, // this is default anyway
  connectionLimit: 10, // this is default anyway
});

module.exports = pool;

The pool does not create all connections upfront but creates them on demand until the connection limit is reached.

app.js

const pool = require('./util/database');

async function insertEmployee(empName, joinDate, age){
  const sql = "INSERT INTO EMPLOYEE (name, join_date, age) values (?, ?, ?)";
  const values = [empName, joinDate, age];
  try{
    const conn = await pool.getConnection();
    const [result, fields] = await conn.execute(sql, values);
    console.log(result);
    console.log(fields);
    conn.release();
  }catch(err){
    console.log(err);
  }
}

insertEmployee('Rajesh', '2023-06-17', 34);

Important points to note here-

  1. insertEmployee() function is a async function as we are using async/await (Promise based API) rather than callback based API.
  2. We are using await with pool.getConnection() method.
  3. By using array destructuring we get the returned values for result and fields.
  4. fields variable contains extra meta data about results, if available.
  5. result contains a ResultSetHeader object, which provides details about the operation executed by the server.
  6. After the task, connection is released using conn.release() which means connection goes back to the pool.

On running the file-

>node app.js

ResultSetHeader {
  fieldCount: 0,
  affectedRows: 1,
  insertId: 1,
  info: '',
  serverStatus: 2,
  warningStatus: 0,
  changedRows: 0
}

undefined

In the above example connection is acquired manually from the pool and manually returned to the pool.

You can also use pool.query() and pool.execute() methods directly. When using these methods connection is automatically released when query resolves.

Here is one more function getEmployees() where pool.query() is used.

async function getEmployees(){
  const sql = "SELECT * FROM EMPLOYEE";
  try{
    const [result, fields] = await pool.query(sql);
    console.log(result);
  }catch(err){
    console.log(err);
  }
}

getEmployees();

On running the file app.js with getEmployee() method-

>node app.js
[
  {
    id: 1,
    name: 'Rajesh',
    join_date: 2023-06-16T18:30:00.000Z,
    age: 34
  }
]

That's all for this topic Node.js - MySQL Connection Pool. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Node.js - How to Connect to MySQL
  2. Writing a File in Node.js

You may also like-

  1. Node.js path.resolve() Method
  2. NodeJS Blocking Non-blocking Code
  3. Java Record Class With Examples
  4. Exception Propagation in Java Exception Handling
  5. Invoking Getters And Setters Using Reflection in Java
  6. React Virtual DOM
  7. Spring Transaction Management Example - @Transactional Annotation and JDBC

Node.js path.resolve() Method

In the post Node.js path.join() Method we saw how path.join() method can be used to join the path segments to form a final path. In Node.js path module there is also a path.resolve() method that is used to resolve path segments into an absolute path.

The given path segments are processed from right to left, with each subsequent path prepended until an absolute path is constructed. Method stops prepending more path segments as soon as an absolute path is formed.

After processing all the given path segments if an absolute path has not yet been generated, the current working directory is used to construct an absolute path.

If no path segments are passed, path.resolve() will return the absolute path of the current working directory.

The resulting path is normalized and trailing slashes are removed unless the path is resolved to the root directory.

path.resolve() method syntax

path.resolve([...paths])

...paths is a sequence of path segments of type string that are resolved into an absolute path.

Method returns a String representing an absolute path.

A TypeError is thrown if any of the arguments is not a string.

path.resolve() method Node.js examples

Suppose I have a Node.js app created under nodews directory with that context let's try to use path.resolve() method to see how absolute paths are formed. We'll also use path.join() with the same path segments to give an idea how path.resolve() differs from path.join() method.

1. Passing various path segments

const path = require('path');

console.log(__dirname);

const filePath = path.join("app", "views", "mypage.html");
console.log('path.join() output:', filePath);

const resolvePath = path.resolve("app", "views", "mypage.html");
console.log('path.resolve() output:', resolvePath);

Output

D:\NETJS\NodeJS\nodews
path.join() output: app\views\mypage.html
path.resolve() output: D:\NETJS\NodeJS\nodews\app\views\mypage.html

As you can see path.join() just adds the path segment and returns it whereas path.resolve() tries to construct an absolute path using passed path segments. Since it is not able to generate an absolute path after processing all given path segments, the current working directory is used to construct an absolute path.

2. Giving one of the path segments with separator.

const path = require('path');

console.log(__dirname);

const filePath = path.join("/app", "views", "mypage.html");
console.log('path.join() output:', filePath);

const resolvePath = path.resolve("/app", "views", "mypage.html");
console.log('path.resolve() output:', resolvePath);

Output

D:\NETJS\NodeJS\nodews
path.join() output: \app\views\mypage.html
path.resolve() output: D:\app\views\mypage.html

As you can see path.join() just adds the path segment and returns it whereas path.resolve() processes the path segments from right to left until an absolute path is constructed. Method is able to form an absolute path when it comes to '/app' path segments.

3. Having more path segments with separator.

const path = require('path');

console.log(__dirname);

const filePath = path.join("/app", "/views", "mypage.html");
console.log('path.join() output:', filePath);

const resolvePath = path.resolve("/app", "/views", "mypage.html");
console.log('path.resolve() output:', resolvePath);

Output

D:\NETJS\ NodeJS\nodews
path.join() output: \app\views\mypage.html
path.resolve() output: D:\views\mypage.html

4. Having separator in the rightmost path segment.

const path = require('path');

console.log(__dirname);

const filePath = path.join("/app", "/views", "/mypage.html");
console.log('path.join() output:', filePath);

const resolvePath = path.resolve("/app", "/views", "/mypage.html");
console.log('path.resolve() output:', resolvePath);

Output

D:\NETJS\NodeJS\nodews
path.join() output: \app\views\mypage.html
path.resolve() output: D:\mypage.html

5. Using '..' (one level up) as one of the path segments.

const path = require('path');

console.log(__dirname);

const filePath = path.join("/app", "/views", "..", "mypage.html");
console.log('path.join() output:', filePath);

const resolvePath = path.resolve("/app", "/views", "..", "mypage.html");
console.log('path.resolve() output:', resolvePath);

Output

D:\NETJS\NodeJS\nodews
path.join() output: \app\mypage.html
path.resolve() output: D:\mypage.html

Here path.resolve() will initially construct the absolute path as D:\views\..\mypage.html which is then normalized to D:\mypage.html

That's all for this topic Node.js path.resolve() Method. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Angular Tutorial Page


Related Topics

  1. Node.js path.basename() Method With Examples
  2. __dirname and __filename in Node.js
  3. NodeJS Event Loop
  4. Node.js - Connect to MySQL Promise API

You may also like-

  1. Difference Between __dirname and process.cwd() in Node.js
  2. Reading a File in Node.js
  3. Node.js Event Driven Architecture
  4. Java ThreadLocal Class With Examples
  5. Why Class Name And File Name Should be Same in Java
  6. Running Dos/Windows Commands From Java Program
  7. Angular Pipes With Examples
  8. Spring Boot Event Driven Microservice With Kafka

Monday, July 1, 2024

Node.js path.join() Method

The path.join() method in Node.js Path module is used to join all given path segments together to form a single well formed path. While forming the path path.join() method takes care of the following.

  1. Uses the platform-specific separator as a delimiter. For example / on POSIX and either \ or / on Windows.
  2. Normalizes the resulting path. While normalizing following tasks are done.
    • Resolves '..' (parent directory or one level up) and '.' (current directory) segments.
    • When multiple, sequential path segment separation characters are found (e.g. / on POSIX and either \ or / on Windows), they are replaced by a single instance of the platform-specific path segment separator (/ on POSIX and \ on Windows).
    • If the path is a zero-length string, '.' is returned, representing the current working directory.

path.join() method syntax

path.join([...paths])

...paths is a sequence of path segments of type string which are joined together to form a path.

Method returns a String representing the final path.

Throws TypeError if any of the path segments is not a string.

path.join() method Node.js examples

1. Joining various path segments

const path = require('path');

const filePath = path.join("app", "views", "mypage.html");
console.log(filePath);

Output

app/views/mypage.html

2. Normalizing path by removing any extra path separators.

const path = require('path');

const filePath = path.join("app", "/views", "//mypage.html");
console.log(filePath);

Output

app/views/mypage.html

3. Using with __dirname to get the path starting from the directory of currently executing file.

const path = require('path');

const filePath = path.join(__dirname, "views", "mypage.html");
console.log(filePath);

Output

D:\NETJS\NodeJS\nodews\views\mypage.html

Same code in Linux system

const path = require('path');

const filePath = path.join(__dirname, "views", "mypage.html");
console.log(filePath);

Output

/home/netjs/nodeapp/views/mypage.html

4. Using '..' path segment to go one level up. For example, if file is executing in directory D:\NETJS\NodeJS\nodews\views\mypage.html then the following code

const path = require('path');

const filePath = path.join(__dirname, "..", "views", "mypage.html");
console.log(filePath);
gives the output as
D:\NETJS\NodeJS\views\mypage.html

It is because the file where this code resides is in D:\NETJS\NodeJS\nodews and '..' path segment means going one level up meaning D:\NETJS\NodeJS

That's all for this topic Node.js path.join() Method. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Angular Tutorial Page


Related Topics

  1. Node.js path.basename() Method With Examples
  2. __dirname and __filename in Node.js
  3. NodeJS Blocking Non-blocking Code
  4. Node.js - How to Connect to MySQL

You may also like-

  1. Appending a File in Node.js
  2. Node.js REPL
  3. Creating HTTP server in Node.js
  4. Difference Between yield And sleep in Java Multi-Threading
  5. Compact Strings in Java
  6. Convert float to String in Java
  7. Directives in Angular
  8. Transaction Management in Spring

Tuesday, June 25, 2024

Node.js - Connect to MySQL Promise API

In the post Node.js - How to Connect to MySQL we have seen how to connect to MySQL using mysql2 package. There callback-based API was used to connect and to run query but mysql2 package also has a Promise based API where you don't need to provide callback functions instead you can use aync/await to make your code more readable.

Creating connection from NodeJS app

Once mysql2 is installed you can use that driver to connect to MySQL and execute queries through your NodeJS app.

For creating a connection you can use createConnection() method, with Promise also you can use one of the following ways to create a connections.

1. Using createConnection(connectionUri)

const mysql = require('mysql2/promise');
try {
  const connection = await mysql.createConnection(
    'mysql://USER_NAME:PASSWORD@localhost:3306/node'
  );
} catch (err) {
  console.log(err);
}

Replace USER_NAME and PASSWORD with your MySQL configured user name and password. Port number used is the default 3306 and it is connecting to DB named node which I have created in MySQL.

2. Using createConnection(config)

You can also call createConnection() by passing a config object which has the required connection options. This is the preferred way to create a connection.

const mysql = require('mysql2/promise');

try {
  const connection = await mysql.createConnection({
  host: 'localhost',
  user: 'USER_NAME',
  password: 'PASSWORD',
  database: 'node', 
  port: 3306
  });
} catch (err) {
  console.log(err);
}

Using MYSQL2 Promise Based API Query Example

Here is a complete example where INSERT statement is used to insert a record into employee table which is created in node schema.

Employee Table

CREATE TABLE `node`.`employee` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(45) NULL,
  `join_date` DATE NOT NULL,
  `age` INT NULL,
  PRIMARY KEY (`id`));

We'll use a separate file to keep DB properties which can then be passed to createConnection() method.

util\config.js

const config = {
  dbproperties: {
    host: 'localhost',
    user: 'root',
    password: 'admin',
    database: 'node', 
    port: 3306
  }
}

module.exports = config;

app.js

const mysql = require('mysql2/promise');
const config = require('./util/config');

async function insertEmployee(){
  const conn = await mysql.createConnection(config.dbproperties);
  const sql = "INSERT INTO EMPLOYEE (name, join_date, age) values ('Rajesh', '2022-06-17', 37)";
  try{
    const [result, fields] = await conn.execute(sql);
    console.log(result);
    console.log(fields);
  }catch(err){
    console.log(err);
  }
}

insertEmployee();

Important points to note here-

  1. insertEmployee() function is a async function as we are using async/await now rather than callback based API.
  2. We are using await with createConnection() method.
  3. By using array destructuring we get the returned values for result and fields.
  4. fields contains extra meta data about results, if available.
  5. result contains a ResultSetHeader object, which provides details about the operation executed by the server.

On running it

>node app.js

ResultSetHeader {
  fieldCount: 0,
  affectedRows: 1,
  insertId: 4,
  info: '',
  serverStatus: 2,
  warningStatus: 0,
  changedRows: 0
}
undefined

From the values displayed you can observe that result.insertId will give you the ID of the inserted record and result.affectedRows will give you the number of rows that are inserted.

Using parameterized query

Above example of insert query has very limited use as values are hardcoded and it can only insert that particular record. In order to make it more generic we can use a parameterized query with placeholders for the values that are passed later.

const mysql = require('mysql2/promise');
const config = require('./util/config');

async function insertEmployee(empName, joinDate, age){
    const conn = await mysql.createConnection(config.dbproperties);
    const sql = "INSERT INTO EMPLOYEE (name, join_date, age) values (?, ?, ?)";
    const values = [empName, joinDate, age];
    try{
        const [result, fields] = await conn.execute(sql, values);
        console.log(result);
        console.log(fields);
      }catch(err){
        console.log(err);
      }
}

insertEmployee('Rajesh', '2022-06-17', 34);

Important points to note here-

  1. insertEmployee() function is a async function and takes 3 parameters for the three fields that are to be inserted into the table. We don’t need to insert id as that will be automatically incremented by DB.
  2. Insert query is parameterized with three placeholders for three values. These values are passed as an array.
    const values = [empName, joinDate, age];
    
  3. In connection.execute() method both query (String) and values (array) are passed. Using the query with placeholders and values parameters, execute() method prepares and queries the statement.

That's all for this topic Node.js - Connect to MySQL Promise API. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. How to Setup a Node.js Project
  2. Writing a File in Node.js

You may also like-

  1. Difference Between __dirname and process.cwd() in Node.js
  2. Binary Search Program in Java
  3. How to Create Immutable Class in Java
  4. What if run() Method Called Directly Instead of start() Method - Java Multi-Threading
  5. Spring Web Reactive Framework - Spring WebFlux Tutorial
  6. Angular Disable Button Example

Node.js - How to Connect to MySQL

In this tutorial we'll see how to connect to MySQL database from Node.js application.

Prerequisite for this tutorial is that you already have MySQL installed in your system.

Installing MySQL driver

To connect to MySQL from NodeJS you need to install MySQL driver for Node.js. We'll use MySQL2 driver which can be installed using the following command.

npm install --save mysql2

Creating connection from NodeJS app

Once mysql2 is installed you can use that driver to connect to MySQL and execute queries through your NodeJS app.

For creating a connection you can use createConnection() method, you can either pass URI or use config object with connection options.

1. Using createConnection(connectionUri)

// Get the client
const mysql = require('mysql2');

const conn = mysql.createConnection(
  'mysql://USER_NAME:PASSWORD@localhost:3306/node'
);

Replace USER_NAME and PASSWORD with your MySQL configured user name and password. Port number used is the default 3306 and it is connecting to DB named node which I have created in MySQL.

2. Using createConnection(config)

You can also call createConnection() by passing a config object which has the required connection options. This is the preferred way to create a connection.

// Get the client
const mysql = require('mysql2');

//create connection to database
const conn = mysql.createConnection({
  host: 'localhost',
  user: 'USER_NAME',
  password: 'PASSWORD',
  database: 'node', 
  port: 3306
})

Once you have the connection object you can use that to call connection() method to explicitly establish a connection with MySQL database.

conn.connect((err) => {
  if(err){
    console.error(err);
    return;
  }
  console.log("connected to DB");
})

Check this post- Node.js - Connect to MySQL Promise API to connect to MySQL database from Node.js using Promise based API provided by mysql2 driver.

Executing query using connection

Here is a complete example where INSERT statement is used to insert a record into employee table which is created in node schema.

CREATE TABLE `node`.`employee` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(45) NULL,
  `join_date` DATE NOT NULL,
  `age` INT NULL,
  PRIMARY KEY (`id`));

database.js

// Get the client
const mysql = require('mysql2');

//create connection to database
const conn = mysql.createConnection({
  host: 'localhost',
  user: 'root',
  password: 'admin',
  database: 'node', 
  port: 3306
})

conn.connect((err) => {
  if(err){
    console.error(err);
    return;
  }
  console.log("connected to DB");
  const sql = "INSERT INTO EMPLOYEE (name, join_date, age) values ('Rajesh', '2022-06-17', 34)";
  // now run query
  conn.query(sql, (err, result, fields) => {
    if(err){
        console.error(err);
        return;
    }
    console.log(result);
    console.log(fields);
  });
})

On running it

>node database.js

connected to DB
ResultSetHeader {
  fieldCount: 0,
  affectedRows: 1,
  insertId: 1,
  info: '',
  serverStatus: 2,
  warningStatus: 0,
  changedRows: 0
}

undefined

Here note that result and fields provide the following information.

  • result: Contains a ResultSetHeader object, which provides details about the operation executed by the server.
  • fields: Contains extra meta data about the operation, if available

You can also implicitly establish a connection by directly invoking a query, no need to explicitly establish a connection using connection() method.

Following code also connects to DB and inserts a record though connect() method is omitted.

// Get the client
const mysql = require('mysql2');

//create connection to database
const conn = mysql.createConnection({
  host: 'localhost',
  user: 'root',
  password: 'admin',
  database: 'node', 
  port: 3306
})

const sql = "INSERT INTO EMPLOYEE (name, join_date, age) values ('Rajesh1', '2022-06-17', 37)";
conn.query(sql, (err, result, fields) => {
  if(err){
      console.error(err);
      return;
  }
  console.log(result);
  console.log(fields);
});

That's all for this topic Node.js - How to Connect to MySQL. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Node.js - Connect to MySQL Promise API
  2. Node.js - MySQL Connection Pool
  3. Node.js MySQL Insert Example
  4. NodeJS Blocking Non-blocking Code
  5. Node.js REPL

You may also like-

  1. NodeJS NPM Package Manager
  2. Creating HTTP server in Node.js
  3. Node.js path.basename() Method With Examples
  4. Java Collections Interview Questions And Answers
  5. How to Loop or Iterate an Arraylist in Java
  6. Spring Web MVC Tutorial
  7. How to Create a Custom Observable in Angular
  8. Convert String to float in Python

Thursday, June 20, 2024

Difference Between __dirname and process.cwd() in Node.js

In this article we'll see the difference between __dirname and process.cwd() method in Node.js.

__dirname in Node.js

__dirname in Node.js is a local variable which stores the absolute path of the directory where the currently executing file (module) resides.

In Node.js, each file is treated as a module and before a module's code is executed, Node.js will wrap it with a function wrapper that looks like the following:

(function(exports, require, module, __filename, __dirname) {
  // Module code actually lives in here
}); 

That's why convenience variables __dirname and __filename, containing the module's absolute filename and directory path are local variables which are specific to the module.

process.cwd() in Node.js

The process.cwd() method returns the current working directory of the Node.js process (not the module).

With process.cwd() working directory depends on from where the node process starts whereas with __dirname working directory depends on the file which is currently executing.

__dirname Vs process.cwd()

Let's try to clear the difference between __dirname and process.cwd() using few examples.

Suppose we have a file pathdemos/pathdemo.js in project root directory.

pathdemos/pathdemo.js

function test(){
    console.log('in function test()');
    console.log('__dirname:', __dirname);

    console.log('process.cwd():', process.cwd())
}

test();

module.exports = {test};

On running this file-

D:\NETJS\NodeJS\nodews\pathdemos>node pathdemo.js

in function test()
__dirname: D:\NETJS\NetJS_2017\NodeJS\nodews\pathdemos
process.cwd(): D:\NETJS\NetJS_2017\NodeJS\nodews\pathdemos

As you can see node invokes pathdemo.js so process.cwd() returns the working directory as path to pathdemo.js. Currently executing file is also pathdemo.js so __dirname also returns the current directory as path to pathdemo.js.

Let's try to execute test() function from some other file. So, we'll remove the test() method execution from pathdemo.js and export the function.

pathdemos/pathdemo.js

function test(){
    console.log('in function test()');
    console.log('__dirname:', __dirname);

    console.log('process.cwd():', process.cwd())
}

module.exports = {test};

There is another file app.js residing in project root directory.

app.js

const p = require('./pathdemos/pathdemo');
p.test();

Check the output by running app.js file.

D:\NETJS\NodeJS\nodews>node app.js

in function test()
__dirname: D:\NETJS\NetJS_2017\NodeJS\nodews\pathdemos
process.cwd(): D:\NETJS\NetJS_2017\NodeJS\nodews

As you see now __dirname is path to pathdemo.js because test() function executes in pathdemo.js where as process.cwd() gives path to project root directory because node invokes app.js so that is the running process.

That's all for this topic Difference Between __dirname and process.cwd() in Node.js. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Node.js Tutorial Page


Related Topics

  1. Node.js REPL
  2. How to Setup a Node.js Project
  3. NodeJS Blocking Non-blocking Code
  4. Node.js path.basename() Method With Examples
  5. Appending a File in Node.js

You may also like-

  1. Synchronization in Java - Synchronized Method And Block
  2. Marker Interface in Java
  3. How to Create PDF From XML Using Apache FOP
  4. BeanPostProcessor in Spring Framework
  5. Angular One-Way Data Binding Using String Interpolation

Wednesday, June 19, 2024

Java Nested Class And Inner Class

In Java programming language you can define a class within another class. Such a class is known as a nested class in Java.


Nested class categories

Java Nested classes are divided into two categories-

  • Static nested classes- Nested classes that are declared static are called static nested classes.

    General form of static nested class in Java-

    class OuterClass {
      ...
      static class StaticNestedClass {
        ...
      } 
    }
    
  • Non-static nested classes- Nested classes that are not static are called Non-static nested classes. They are known better as inner classes in Java.

    General form of inner class in Java-

    class OuterClass {
      ...
      class InnerClass {
        ...
      }
    }
    

Java Static nested class example

public class NestedDemo {
 int num = 10;
 public static class Nested{
  NestedDemo nd = new NestedDemo();
  private int quantity = 10;
  void msg(){
   System.out.println("data is "+ nd.num * quantity);
  }
 }
 public static void main(String[] args) {
  NestedDemo.Nested nested = new NestedDemo.Nested();
  nested.msg();
 }
}

Output

data is 100

Benefits of using Nested Classes in Java

  1. Nested classes provide a way to logically group classes that are only used in one place.
    If a class is useful to only one other class, then it makes sense to embed it in that class and keep the two together. Nesting such "helper classes" makes their package more streamlined.
  2. It increases encapsulation. Note that a nested class has access to all the members of the outer class even private members. Consider two top-level classes, A and B, where B needs access to members of A that would otherwise be declared private. By hiding class B within class A, A's members can be declared private and B can access them. In addition, B itself can be hidden from the outside world.
  3. It can lead to more readable and maintainable code: Nesting small classes within top-level classes places the code closer to where it is used.

Important points about static nested class

  1. Just like static class methods, a static nested class cannot refer directly to instance variables or methods defined in its enclosing class, it can use them only through an object reference.
  2. Static nested classes are accessed using the enclosing class name: NestedDemo.Nested
  3. Since nested class is a member of its enclosing class, a nested class can have any of the access modifiers; private, public, protected, or package private. Note that outer classes can only be declared public or package private.

Inner class in Java

An inner class is a nested class that is not static. Inner class has access to all the members (fields and methods) of the outer class including those with access modifier as private. Let’s see a simple inner class example here to make it clearer.

Java Inner class example

In this example there is a OuterClass with one private field, a method createInner() and an inner class InnerClass. Inner class has one method displayMsg() which takes String as argument.

class OuterClass {
 private int outerVar = 12;
 // Inner class
 class InnerClass{
  void displayMsg(String msg){
   System.out.println("Message is - " + msg);
   System.out.println("Outer class variable - " + outerVar);
  }
 }
 
 void createInner(){
  InnerClass ic = new InnerClass();
  ic.displayMsg("Calling From a method with in the Outer class");
 }
}

public class ICDemo {
 public static void main(String[] args) {
  OuterClass oc = new OuterClass();
  oc.createInner();
  // Creating inner class object using outer class object
  OuterClass.InnerClass oic = oc.new InnerClass();
  oic.displayMsg("Calling from outside the OuterClass scope");
 }
}

Output

Message is - Calling From a method with in the Outer class
Outer class variable - 12
Message is - Calling from outside the OuterClass scope
Outer class variable - 12

Points to note

There are several points of interest to note here about the inner classes–

  1. From the output you can see that inner class has access to fields and methods of the outer class, even if they are private. In the displayMsg() method of the inner class outerVar variable is accessed which is private and resides with in the scope of outer class.
  2. If you want to make an object of the inner class with in a non-static method of the outer class you don’t need to qualify it with Outer class name. Since createInner() method is a method of the outer class and it is not static you can create an object of the inner class directly.
  3. If you want to make an object of the inner class outside the scope of the outer class or from a method with in the outer class which is static you have to qualify inner class with the outer class so the type of the object would be specified as OuterClassName.InnerClassName. You can see example of object creation of inner class that way in the main method as it resides in another class ICDemo.
  4. An inner class can be private, public, protected or package-private. Note that normal class can only be public or package-private (default).

Types of inner classes

Apart from non-static nested class (also known as member inner class) there are two additional types of inner classes in Java.

  • Local inner class
  • Anonymous inner class

Local inner class in Java

Local inner classes are inner classes that can be defined within a block, here block means any group of zero or more statements between balanced braces. Generally you will find local inner classes defined within a method body.

Java Local inner class example

Let’s see an example of local inner class where inner class is defined in the method msg. Here Local inner class is also implementing an interface Message.

package org.prgm;
// Interface
interface Message{
 String readMsg();
}

class Outer {
 private int outerVar = 12;
 public Message msg(String str){
  // Local variable - it has to be final or
  // effectively final
  String hello = "Hello ";
  // Local Inner class
  class InnerMsg implements Message{
   
   private String msg;
   
   InnerMsg(String msg){
    this.msg = msg;
   }
   @Override
   // implementing interface method
   public String readMsg() {
    //hello = "Hi";
    System.out.println("I can read outer class variable its value is - " + outerVar );
    return hello + msg;
   }   
  }
  return new InnerMsg(str); 
 }
}
public class ICLocalDemo {

 public static void main(String[] args) {
  Outer outer = new Outer();
  Message message = outer.msg("Local Inner Class");
  String temp = message.readMsg();
  System.out.println("temp -- " + temp); 
 }
}

Output

I can read outer class variable its value is - 12
temp -- Hello Local Inner Class

Points to note

There are several points of interest in the above code so let’s go through those points and try to get a better explanation.

  1. Here inner class InnerMsg is defined with in the method msg that is why it is local inner class as it is local to the method msg.
  2. Local inner class can access members of the enclosing class, you can see that int variable outerVar is accessed with in the inner class InnnerMsg.
  3. A local class has access to local variables (variables defined inside the method body). However, a local class can only access local variables that are declared final (before Java 8).
  4. Starting in Java SE 8, local class can access local variables and parameters of the enclosing block that are final or effectively final. A variable or parameter whose value is never changed after it is initialized is effectively final. In the method readMsg() if you uncomment the line- //hello = "Hi"; You will get the error “Local variable hello defined in an enclosing scope must be final or effectively final” if you are running this code in Java 8. If you are using version lesser than 8 then it will ask you to declare hello as final.
  5. In the above code one thing to note is that inner class implements an interface. Doing that you are abiding to a very important point of object oriented programming – Abstraction. If you have noticed the return type of the method msg is interface Message. That way your implementation of the inner class is completely hidden.

Anonymous inner class in Java

Anonymous inner class is a type of local inner class that has no name. You will always declare anonymous inner class as subclass or as implementation of an interface. Note that you cannot declare constructors in an anonymous class.

Java Anonymous inner class example

Let’s implement the same example as above as an anonymous inner class. There is an interface Message and that is implemented as an anonymous inner class with in the method msg.

//Interface
interface Message{
 String readMsg();
}

class MessageOuter {
 private int outerVar = 12;
 public Message msg(String str){
  // Local variable - it has to be final or
  // effectively final
  String hello = "Hello ";
  return new Message(){
   @Override
   public String readMsg() {
    //hello = "Hi";
    System.out.println("I can read outer class variable its value is - " + outerVar );
    return hello + str;
   }   
  }; // required to have semicolon
 }
}

/**
 * 
 */
public class ICAnonymousDemo {
 public static void main(String[] args) {
  MessageOuter mo = new MessageOuter();
  Message msg = mo.msg("Anonymous Inner Class");
  System.out.println("Message is - " + msg.readMsg());
 }
}

Output

I can read outer class variable its value is - 12
Message is - Hello Anonymous Inner Class

Points to note

There are several points of interest in the above code so let’s go through those points and try to get a better explanation.

  1. Here inner class with in the method msg is an anonymous inner class. It contains a new operator, name of the interface it is implementing (it can also extend a class), and class declaration body with in the braces.
  2. Because an anonymous class definition is an expression, it must be part of a statement. That is why there is a semicolon after the closing brace.
  3. Anonymous inner class can access members of the enclosing class, you can see that int variable outerVar is accessed with in the method of the anonymous inner class.
  4. Anonymous inner class has access to local variables (variables defined inside the method body). Same rules apply as in the case of local inner class.
  5. You cannot declare constructors in an anonymous class as it has no name.

That's all for this topic Java Nested Class And Inner Class. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Basics Tutorial Page


Related Topics

  1. Serialization and Deserialization in Java
  2. Java Object Cloning - clone() Method
  3. final Keyword in Java With Examples
  4. Effectively Final in Java 8
  5. Lambda Expressions in Java 8

You may also like-

  1. BigDecimal in Java With Examples
  2. Java split() Method - Splitting a String
  3. Java Program to Find The Longest Palindrome in a Given String
  4. Parallel Stream in Java Stream API
  5. Deadlock in Java Multi-Threading
  6. How to Inject Prototype Scoped Bean into a Singleton Bean in Spring
  7. Creating New Component in Angular
  8. Python First Program - Hello World

Tuesday, June 18, 2024

DatabaseMetaData Interface in Java-JDBC

DatabaseMetaData in Java, which resides in java.sql package, provides information about the database (DB meta data) you are connected to.

Using the methods provided by Java DatabaseMetaData interface you can get information about-

  • Database like DB name and version
  • JDBC driver like the driver’s name and version,
  • names of DB schemas,
  • name of tables in any DB schema,
  • names of views,
  • information about the procedures.

In this post we’ll see examples of some of the commonly used methods. You can get the list of full methods here- https://docs.oracle.com/javase/9/docs/api/java/sql/DatabaseMetaData.html


How to get DatabaseMetaData object in JDBC

You can get the DatabaseMetaData instance by calling the getMetaData() method of the Connection class.

DatabaseMetaData dbMetaData = connection.getMetaData();

DatabaseMetaData example-Getting DB product and version information

This example code shows how you can get DB name and version information using DatabaseMetaData in JDBC.

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.SQLException;

public class DBMetaData {

 public static void main(String[] args) {
  Connection connection = null;
   try {
    // Loading driver
    Class.forName("com.mysql.jdbc.Driver");
    
    // Creating connection
    connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/netjs", 
                        "root", "admin");
    
    DatabaseMetaData dbMetaData = connection.getMetaData();
    
    System.out.println("Database Name - " + dbMetaData.getDatabaseProductName());
    System.out.println("Database Version - " + dbMetaData.getDatabaseProductVersion());
    System.out.println("Database Major Version - " + dbMetaData.getDatabaseMajorVersion());
    System.out.println("Database Minor Version - " + dbMetaData.getDatabaseMinorVersion());
    System.out.println("Database User - " + dbMetaData.getUserName());
    
   } catch (ClassNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
   } catch (SQLException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
   }finally{
       if(connection != null){
         //closing connection 
         try {
           connection.close();
         } catch (SQLException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
         }
       } // if condition
   }// finally
 }
}

DatabaseMetaData example - Getting driver information

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.SQLException;

public class DBMetaData {
  public static void main(String[] args) {
    Connection connection = null;
    try {
      // Loading driver
      Class.forName("com.mysql.jdbc.Driver");
      
      // Creating connection
      connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/netjs", 
                       "root", "admin");
      
      DatabaseMetaData dbMetaData = connection.getMetaData();
      
      System.out.println("Driver Name - " + dbMetaData.getDriverName());
      System.out.println("Driver Version - " + dbMetaData.getDriverVersion());
      System.out.println("Driver Major Version - " + dbMetaData.getDriverMajorVersion());
      System.out.println("Driver Minor Version - " + dbMetaData.getDriverMinorVersion());
      System.out.println("JDBC Major Version - " + dbMetaData.getJDBCMajorVersion());
      System.out.println("JDBC Minor Version - " + dbMetaData.getJDBCMinorVersion());
    } catch (ClassNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (SQLException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
   }finally{
      if(connection != null){
        //closing connection 
        try {
          connection.close();
        } catch (SQLException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      } // if condition
    }// finally
  }
}

Example to get tables using DatabaseMetaData in JDBC

For getting tables you can use getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types) method. You can provide null as value for all the parameters, that way you don’t narrow the search and all the tables are returned. If you want to narrow your search to get specific tables then you can provide values for these parameters.

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;

public class DBMetaData {
  public static void main(String[] args) {
    Connection connection = null;
    try {
      // Loading driver
      Class.forName("com.mysql.jdbc.Driver");
    
      // Creating connection
      connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/world", 
                        "root", "admin");
    
      DatabaseMetaData dbMetaData = connection.getMetaData();
      
      ResultSet rs = dbMetaData.getTables(null, null, null, null);
      while (rs.next()){
        System.out.println("Table name " + rs.getString(3));
      }
    } catch (ClassNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (SQLException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }finally{
      if(connection != null){
        //closing connection 
        try {
          connection.close();
        } catch (SQLException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      } // if condition
    }// finally
  }
}

Output

Table name city
Table name country
Table name countrylanguage

Here I am connecting to “world” schema in MySQL and getting all the tables.

Each table description in the returned ResultSet has the following columns:

Table Description Columns
Column Name Type Description
TABLE_CAT String table catalog (may be null)
TABLE_SCHEM String table schema (may be null)
TABLE_NAME String table name
TABLE_TYPE String table type. Typical types are "TABLE", "VIEW" etc.
REMARKS String explanatory comment on the table (may be null)
TYPE_CAT String the types catalog (may be null)
TYPE_SCHEM String the types schema (may be null)
TYPE_NAME String type name (may be null)
SELF_REFERENCING_COL_NAME String name of the designated "identifier" column of a typed table (may be null)
REF_GENERATION String specifies how values in SELF_REFERENCING_COL_NAME are created.

That’s why column index is 3 while getting result from ResultSet as TABLE_NAME is at number 3.

Example to get Procedures using DatabaseMetaData in JDBC

For getting procedures you can use getProcedures(String catalog, String schemaPattern, String procedureNamePattern) method. Again you can pass null as value for all the parameters if you don’t want to narrow the search.

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;

public class DBMetaData {

 public static void main(String[] args) {
  Connection connection = null;
   try {
    // Loading driver
    Class.forName("com.mysql.jdbc.Driver");
    
    // Creating connection
    connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/netjs", 
                        "root", "admin");
    
    DatabaseMetaData dbMetaData = connection.getMetaData();
    
    ResultSet rs = dbMetaData.getProcedures(null, null, null);
    
    while (rs.next()){
     System.out.println("Procedure name " + rs.getString(3));
    }
    
   } catch (ClassNotFoundException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
   } catch (SQLException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
   }finally{
       if(connection != null){
          //closing connection 
          try {
            connection.close();
          } catch (SQLException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
          }
       } // if condition
   }// finally
 }
}

Each procedure description in the returned ResultSet has the following columns:

Procedure Description Columns
Column Name Type Description
PROCEDURE_CAT String procedure catalog (may be null)
PROCEDURE_SCHEM String procedure schema (may be null)
PROCEDURE_NAME String procedure name
reserved for future use
reserved for future use
reserved for future use
REMARKS String explanatory comment on the procedure
PROCEDURE_TYPE short type name (may be null)
SPECIFIC_NAME String The name which uniquely identifies this procedure within its schema.

That’s why column index is 3 while getting result from ResultSet as PROCEDURE_NAME is at number 3.

That's all for this topic DatabaseMetaData Interface in Java-JDBC. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Advanced Tutorial Page


Related Topics

  1. DataSource in Java-JDBC
  2. Java JDBC Steps to Connect to DB
  3. Statement Interface in Java-JDBC
  4. ResultSet Interface in Java-JDBC
  5. Data access in Spring framework

You may also like-

  1. How LinkedList Class Works Internally in Java
  2. Difference Between HashMap And ConcurrentHashMap in Java
  3. Java ReentrantReadWriteLock With Examples
  4. Livelock in Java Multi-Threading
  5. Enum Type in Java
  6. interface static methods in Java 8
  7. Arrange Non-Negative Integers to Form Largest Number - Java Program
  8. Print Odd-Even Numbers Using Threads And wait-notify Java Program