NamedParameterJdbcTemplate unit test - java

How to create unit test of this service class:
#Service
public class PhoenixService implements IPhoenixService {
private Logger log = LoggerFactory.getLogger(PhoenixService.class);
private static final String WHERE = " WHERE ";
private static final String FROM = " FROM ";
private static final String SELECT = "SELECT ";
#Autowired
#Qualifier("phoenixNamedParameterJdbcTemplate")
private NamedParameterJdbcTemplate phoenixNamedParameterJdbcTemplate;
#Override
public List<Account> getInternalAccount(String accountNo) throws Exception {
MapSqlParameterSource parameters = new MapSqlParameterSource();
parameters.addValue("accountNo", accountNo);
String queryGetId = SELECT + ACCOUNT_IDENTIFIER + FROM
+ "SCHEMA" + "."
+ ACCOUNT + WHERE
+ ACCOUNT_NUMBER_TEXT + " = :accountNo";
List<Account> accounts = phoenixNamedParameterJdbcTemplate.query(queryGetId, parameters,
new RowMapper());
if (accounts.isEmpty()) {
//SomeThing
}
return accounts;
}
}
I try to search but none working.
Sorry I new to Java especially unit test
Additional info, my environment didnt allow connection to DB for unit test.
Thanks

Related

How to Update a SQL database Table if the entity is Persistable in Spring Boot JPA

I have created a Spring Boot JPA Application, In that, I have made an entity persistable.
as Shown Below.
this is my code for creating an entity:
#Getter
#Setter
#ToString
#Entity
public class TableModel implements Persistable<String> {
#Override
public String toString() {
return "TableModel [PrimaryKey=" + PrimaryKey + ", Term_Guid=" + Term_Guid + ", Term_Name=" + Term_Name
+ ", Term_Description=" + Term_Description + ", Term_Qualified_Name=" + Term_Qualified_Name
+ ", Term_Status=" + Term_Status + ", Term_Created_Date=" + Term_Created_Date + ", Term_Updated_Date="
+ Term_Updated_Date + ", Report_name=" + Report_name + ", Report_Guid=" + Report_Guid + ", Report_Type="
+ Report_Type + ", classification=" + classification + ", Term_Expert_Username=" + Term_Expert_Username
+ ", Term_Steward_Username=" + Term_Steward_Username + ", Report_Expert_Username="
+ Report_Expert_Username + ", Report_Owner_Username=" + Report_Owner_Username + ", Sql_db_load_time="
+ Sql_db_load_time + "]";
}
#Id
#Column(name = "Primary_Key")
private String PrimaryKey;
#Column(name = "Term_Guid")
private String Term_Guid;
#Column(name = "Term_Name")
private String Term_Name;
#Column(name = "Term_Description",columnDefinition = "nvarchar(MAX)")
private String Term_Description;
#Column(name = "Term_Qualified_Name")
private String Term_Qualified_Name;
#Column(name = "Term_Status")
private String Term_Status;
#Temporal(TemporalType.TIMESTAMP)
private java.util.Date Term_Created_Date;
#Temporal(TemporalType.TIMESTAMP)
private java.util.Date Term_Updated_Date;
#Column(name = "Report_name")
private String Report_name;
#Column(name = "Report_Guid")
private String Report_Guid;
#Column(name = "Report_Type")
private String Report_Type;
#Column(name = "Classification")
private String classification;
#Column(name = "Term_Expert_Username")
private String Term_Expert_Username;
#Column(name = "Term_Steward_Username")
private String Term_Steward_Username;
#Column(name = "Report_Expert_Username")
private String Report_Expert_Username;
#Column(name = "Report_Owner_Username")
private String Report_Owner_Username;
#Temporal(TemporalType.TIMESTAMP)
private java.util.Date Sql_db_load_time;
#Override
public boolean isNew() {
// TODO Auto-generated method stub
return true;
}
#Override
public String getId() {
// TODO Auto-generated method stub
return null;
}
}
By using this Code I am able to insert data successfully
but if I want to update the data which is inserted I m not able do,
Please Suggest how I can update the data if the entity is persistable using Springboot jpa
If you are not clear how to fire update queries with spring data jpa,
You can refer this document for partial updates:
https://www.baeldung.com/spring-data-partial-update
You can also refer spring data jpa documentation.
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.modifying-queries
I suggest you keep your entity simple, then create a repository that extends JpaRepository or CrudRepository where you can write your queries
#Repository
public interface TableModelRepository extends JpaRepository<TableModel, String>{
#Modifying
#Query("update TableModel u set u.firstname = ?1 where u.lastname = ?2")
void updateTable(String firstname, String lastname);
}
create a service class where you can perform the update
#Service
public class TableModelServices{
#Autowired
private TableModelRepository tableModelRepository;
#Override
public String updateTable(String firstname, String lastname) {
tableModelRepository.updateTable(firstname, lastname);
return null;
}
}
the above codes are for reference, I will mention some links which will help you more
https://www.baeldung.com/spring-data-jpa-dynamicupdate
https://www.baeldung.com/spring-data-partial-update
you can refer to these two links.

Using jdbcTemplate.query with parameters

I have 3 tables in Database Lecture--< LectureGroups >-- Groups.
And I want to get schedule for a certain group on a certain day. I try to do it in this way:
#Repository
public class Schedule {
private static final String GET_GROUP_DAY_SCHEDULE = "SELECT * FROM LECTURES " +
"INNER JOIN LECTUREGROUPS ON LECTURES.ID = LECTUREGROUPS.LECTUREID " +
"INNER JOIN GROUPS ON GROUPS.ID = LECTUREGROUPS.GROUPID " +
"WHERE GROUPID = :GROUPID AND DATE = :DATE";
#Autowired
private JdbcTemplate jdbcTemplate;
public List<Lecture> getGroupDayLectures(int groupId, LocalDateTime dateTime) {
MapSqlParameterSource parameters = new MapSqlParameterSource()
.addValue("groupid", groupId)
.addValue("date", dateTime);
return jdbcTemplate.query(GET_GROUP_DAY_SCHEDULE, new BeanPropertyRowMapper<>(Lecture.class), parameters);
}
}
But I get an exception in query raw
Caused by: org.postgresql.util.PSQLException: Can't infer the SQL type to use for an instance of org.springframework.jdbc.core.namedparam.MapSqlParameterSource. Use setObject() with an explicit Types value to specify the type to use.
How I can fix it?
I also used variant with
private static final String GET_GROUP_DAY_SCHEDULE = "SELECT * FROM LECTURES " +
"INNER JOIN LECTUREGROUPS ON LECTURES.ID = LECTUREGROUPS.LECTUREID " +
"INNER JOIN GROUPS ON GROUPS.ID = LECTUREGROUPS.GROUPID " +
"WHERE GROUPID = ? AND DATE = ?";
#Autowired
private JdbcTemplate jdbcTemplate;
public List<Lecture> getGroupDayLectures(int groupId, LocalDateTime dateTime) {
return jdbcTemplate.query(GET_GROUP_DAY_SCHEDULE, new Object[]{groupId, dateTime}, new BeanPropertyRowMapper<>(Lecture.class));
}
and it works but return only 1 Lecture in list (it must be 3)
There is a signature with parameters in the jdbcTemplate class:
public <T> List<T> query(String sql, RowMapper<T> rowMapper, #Nullable Object... args)
So it is very easy to use it in this way
private static final String GET_GROUP_DAY_SCHEDULE = "SELECT * FROM LECTURES " +
"INNER JOIN LECTUREGROUPS ON LECTURES.ID = LECTUREGROUPS.LECTUREID " +
"INNER JOIN GROUPS ON GROUPS.ID = LECTUREGROUPS.GROUPID " +
"WHERE GROUPID = ? AND DATE = ?";
#Autowired
private JdbcTemplate jdbcTemplate;
public List<Lecture> getGroupDayLectures(int groupId, LocalDate date) {
return jdbcTemplate.query(GET_GROUP_DAY_SCHEDULE, new BeanPropertyRowMapper<>(Lecture.class), groupId, date);
}

Update Database with JDBC having some values which should be ignored

I am having some troubles using JDBC for updating a table-column. If I have a table e.g User(name,address,hobby,...) imagine about 15 fields. Then I get via frontend an Object from a form, where a user can type in all entries which should be changed. Now I need to save the changes in the database, but not all of the fields got changed, so my DAO has some null values. For example name and address should be changed, the other entries in the table shouldn't. Is there any smart way to put that into a JDBC PreparedStatement? Or do you know other solutions? I am trying to avoid a lot of value != null statements.
Thanks in advance!
(I am using spring as my backend, and angular in frontend)
Since you're using Spring, you can use the NamedParameterJdbcTemplate, but the real trick is the use of COALESCE to use a fall-back value when the value given is NULL:
#Autowired
private DataSource dataSource;
public void updateUser(int id, String name, String address, String hobby) {
NamedParameterJdbcTemplate jdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
String sql = "UPDATE User" +
" SET Name = COALESCE(:name, Name)" +
", Address = COALESCE(:address, Address)" +
", Hobby = COALESCE(:hobby, Hobby)" +
" WHERE Id = :id";
MapSqlParameterSource paramMap = new MapSqlParameterSource();
paramMap.addValue("id" , id , Types.INTEGER);
paramMap.addValue("name" , name , Types.VARCHAR);
paramMap.addValue("address", address, Types.VARCHAR);
paramMap.addValue("hobby" , hobby , Types.VARCHAR);
if (jdbcTemplate.update(sql, paramMap) == 0)
throw new EmptyResultDataAccessException("User not found: " + id, 1);
}
Or, if you use a POJO with the user data:
public class User {
private int id;
private String name;
private String address;
private String hobby;
// Getters and setters here
}
public void updateUser(User user) {
NamedParameterJdbcTemplate jdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
String sql = "UPDATE User" +
" SET Name = COALESCE(:name, Name)" +
", Address = COALESCE(:address, Address)" +
", Hobby = COALESCE(:hobby, Hobby)" +
" WHERE Id = :id";
BeanPropertySqlParameterSource paramMap = new BeanPropertySqlParameterSource(user);
if (jdbcTemplate.update(sql, paramMap) == 0)
throw new EmptyResultDataAccessException("User not found: " + id, 1);
}
The simple solution you can have is using SimpleJdbcInsert and adding usingGeneratedKeyColumns("ID").
#Autowired
private DataSource dataSource;
#Override
public ResponseEntity<Void> insertEntity(Entity obj) {
SimpleJdbcInsert simpleJdbcInsert = new SimpleJdbcInsert(jdbcTemplate.getDataSource());
simpleJdbcInsert.withTableName(TABLE_APP_REPO).usingGeneratedKeyColumns("ID");
BeanPropertySqlParameterSource paramSource = new BeanPropertySqlParameterSource(obj);
try {
simpleJdbcInsert.execute(paramSource);
} catch (Exception e) {
return ResponseEntity.badRequest().build();
}
return ResponseEntity.ok().build();
}

HIbernate JPA Query from Different Sources not Generating Proper Jackson JSON Response

I am retrieving data from multiple tables/POJO's.I want the data in JSON format.In Pojo classes I am using #JsonProperty.Still I am not getting result Json in desired format.
My result:
[["2017 Sprint 1","Android development",23/12/2016,16/01/2017]]
I want result in format {
"iteration": "2017 Sprint 1",
"project": "MDM - Core & Integration",
"isd": "23/12/2016",
"ied": "16/01/2017",
My main controller method:
#Controller
#RequestMapping("/json/retrospective")
public class MainControllerClass
{
#RequestMapping(value="{userid}", method = RequestMethod.GET,produces=MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public List<Details> getInfoInJSON(#PathVariable int userid)
{
Configuration con = new Configuration();
con.configure("hibernate.cfg.xml");
SessionFactory SF = con.buildSessionFactory();
Session session= SF.openSession();
Query test=session.createQuery("select itr.iteration_name,prj.project_name,itr.isd,itr.ied from RetrospectiveInfo retro,IterationInfo itr,ProjectInfo prj where retro.retrospective_id ="+userid+" and retro.project_id = prj.project_id and retro.iteration_id = itr.iteration_id");
List<Details> details= test.list();
session.close();
SF.close();
return details;
}
}
Class details:
public class Details
{
#JsonProperty("iteration")
private String iteration;
#JsonProperty("project")
private String project;
#JsonProperty("isd")
private Date isd;
#JsonProperty("ied")
private Date ied;
getter/setters
I have got 3 Jackson jars annotation,databind and core of latest version 2.8 in buildpath.Why I am I getting such a result??What changes do I need to make in my code??Are any jars to be added??kindly help
The main issue is that your are constructing a Details class that is formed from a JPA query using different types check (Error: Cannot create TypedQuery for query with more than one return)
To resolve the issue, create a constructor for the required JSON attributes
package com.sof.type;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
#JsonPropertyOrder({ "iteration", "project", "isd", "ied"})
public class Details {
#JsonProperty
private String iteration;
#JsonProperty
private String project;
#JsonProperty
private String isd;
#JsonProperty
private String ied;
public Details(String iteration, String project, String isd, String ied) {
this.iteration = iteration;
this.project = project;
this.isd = isd;
this.ied = ied;
}
}
Then use it this way
#PersistenceContext
private EntityManager em;
or
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("com.sof");
EntityManager em = entityManagerFactory.createEntityManager();
with
List<Details> details = em.createQuery(
"SELECT NEW com.sof.type.Details(itr.iteration_name, prj.project_name, itr.isd, itr.ied) " +
"FROM RetrospectiveInfo retro, " +
" IterationInfo itr, " +
" ProjectInfo prj " +
"WHERE retro.retrospective_id = :userId " +
"AND retro.project_id = prj.project_id " +
"AND retro.iteration_id = itr.iteration_id", Details.class)
.setParameter("userId", userid)
.getResultList();

how to use an inner abstract class without using its parent class name in another class in android

public final class FeedReaderContract {
// To prevent someone from accidentally instantiating the contract class,
// give it an empty constructor.
public FeedReaderContract() {}
/* Inner class that defines the table contents */
public static abstract class FeedEntry implements BaseColumns {
public static final String TABLE_NAME = "entry";
public static final String COLUMN_NAME_ENTRY_ID = "entryid";
public static final String COLUMN_NAME_TITLE = "title";
public static final String COLUMN_NAME_SUBTITLE = "subtitle";
...
}
}
when i do
private static final String SQL_CREATE_ENTRIES =
"CREATE TABLE " + FeedEntry.TABLE_NAME + " (" +
FeedEntry._ID + " INTEGER PRIMARY KEY," +
FeedEntry.COLUMN_NAME_ENTRY_ID + TEXT_TYPE + COMMA_SEP +
FeedEntry.COLUMN_NAME_TITLE + TEXT_TYPE + COMMA_SEP +
... // Any other options for the CREATE command
" )";
I am not able to use FeedEntry directly. I have to use FeedReaderContract.FeedEntry.COLUMN_NAME instead of FeedEntry.COLUMN_NAME.
How to use FeedEntry directly??

Categories