Java overriding static method - java

I have found myself in the need to override a static method, simply because it makes most sense, but I also know this is not possible.
The superclass, Entity.java:
abstract public class Entity<T> {
public Entity() {
//set up database connection
}
abstract public static Map<Object, T> getAll();
abstract public void insert();
abstract public void update();
protected void getData(final String query) {
//get data via database
}
protected void executeQuery(final String query) {
//execute sql query on database
}
}
One of the many concrete implementations, Account.java:
public class Account extends Entity<Account> {
private final static String ALL_QUERY = "SELECT * FROM accounts";
private final static String INSERT_QUERY = "INSERT INTO accounts (username, password) VALUES(?, ?)";
private final static String UPDATE_QUERY = "UPDATE accounts SET password=? WHERE username=?";
private String username;
private String password;
public Account(final String username, final String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(final String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(final String password) {
this.password = password;
}
#Override
public static Map<Object, Account> getAll() {
//return a map using the ALL_QUERY string, calls getData(string);
}
#Override
public void insert() {
//insert this using INSERT_QUERY, calls executeQuery(string);
}
#Override
public void update() {
//update this using UPDATE_QUERY, calls executeQuery(string);
}
}
I haven't been going in depth explaining the code, but any general feedback on it would also be appreciated, I hope the comments explain enough.
So basically I think we can all agree that using Account.getAll() makes more sense over new Account().getAll() (if I would introduce a dummy syntax for it).
However I do want to have it extend the Entity class, currently it is only for convienience, but later on I may have to use sets/lists/multisets of Entity and perform an update() action on all of them, for example if I would build some queue that performances all updates every minute.
So well, is there a way to construct getAll() correctly?
Regards.

You could have separate classes for operations on all elements:
abstract public class Collection<T extends Entity<T>> {
abstract public static List<T> getAll();
public void printAll() {
// Print all entries of List obtained from getAll()
}
}
Which you could use as:
public class Accounts extends Collection<Account> {
#Override
public List<Account> getAll() {
//return a list using the ALL_QUERY string, calls getData(string);
}
}

It doesn't seems to me that it is really "simply because it makes most sense".
Tying persistence at your entity is not a good idea. There are already lots of patterns that give an appropriate design on this problem.
For example, in Domain Driven Design, "Persistence Ignorance" is what people trying to achieve. Consider making a Repository for each of your entity:
interface Repository<T> {
List<T> findAll();
void insert(T);
void update(T);
}
so you can override it by whatever way you want:
interface UserRepository extends Repository<User> {
// some other methods which is meaningful for User
User findByLoginName(String loginName);
}
class UserRepositoryImpl implements UserRepository {
List<User> findAll() {
// call whatever query
}
void insert(T){...}
void update(T){...}
User findByLoginName(String loginName) {...}
}
With a proper design and a component to handle the retrieval/storage of entity, you can have a less-persistence-coupled entity, and with repository that can perform proper "overriding".

Related

How to pass multiple Types that implement the same interface?

Firstly apologies about the not so great title, I am new to Java and wasn't sure how to title this.
I have a interface class "TestInterface":
ublic interface TestInterface {
String getForename();
void setForename(String forename);
String getSurname();
void setSurname(String surname);
}
"TestImpl" implements "TestInterface":
public class TestImpl implements TestInterface{
private String forename;
private String surname;
#Override
public String getForename() {
return forename;
}
public void setForename(String forename) {
this.forename = forename;
}
#Override
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
}
Then I have a call called "ExtendTest" which extends "TestImpl":
public class ExtendTest extends TestImpl{
private String firstLineAddress;
public String getFirstLineAddress() {
return firstLineAddress;
}
public void setFirstLineAddress(String firstLineAddress) {
this.firstLineAddress = firstLineAddress;
}
}
I then have this "Entity" class:
import java.util.List;
public class Entity {
private List<TestInterface> testInterfaces;
private List<ExtendTest> extendTests;
public List<TestInterface> getTestInterfaces() {
return testInterfaces;
}
public void setTestInterfaces(List<TestInterface> testInterfaces) {
this.testInterfaces = testInterfaces;
}
public List<ExtendTest> getExtendTests() {
return extendTests;
}
public void setExtendTests(List<ExtendTest> extendTests) {
this.extendTests = extendTests;
}
}
and finally this "DoStuff" class where the dostuff method accepts a parameter of type List
import java.util.List;
public class DoStuff {
public void doStuff(List<TestInterface> testData) {
}
}
I try to test this like so:
public class Main {
public static void main(String[] args) {
System.out.println("Hello, World!");
DoStuff doStuff = new DoStuff();
Entity entity = new Entity();
// Works
doStuff.doStuff(entity.getTestInterfaces());
// Does not work
doStuff.doStuff(entity.getExtendTests());
}
}
However where the comment is "Does not work" their is an error
Required type:
List<TestInterface>
Provided:
List<ExtendTest>
My question is how do I make it so that I can pass it in. My understanding was that becase they all implement TestInterface that it would work but I think I am wrong with this.
Thanks for any help and learnings here :)
You've run afoul of PECS. I recommend reading the linked answer for a more detailed explanation, but here's the bits specific to your use case.
When you have a generic type (List, in your case), if you only read from it, you should write List<? extends MyInterface>. If you only write to it, you should write List<? super MyInterface>. If you do both, then you want List<MyInterface>. Why do we do this? Well, look at your code.
public void doStuff(List<TestInterface> testData) { ... }
This function takes a List<TestInterface>. The List interface has a ton of capability. You can add and remove things to it in addition to just reading from it. And doStuff expects a list of TestInterface. So it's entirely fair game for the implementation of doStuff to do
testData.add(new ClassIJustMadeUp());
assuming ClassIJustMadeUp implements TestInterface. So we definitely can't pass this function a List<ExtendTest>, since that list type can't contain ClassIJustMadeUp.
However, if your function does only read from the list and isn't planning to add anything to it, you can write the signature as
public void doStuff(List<? extends TestInterface> testData) { ... }
and now you can pass a List of any type which extends TestInterface. It's fine to read from this list, since any type which extends TestInterface clearly can be upcast safely to TestInterface. But if we try to add a list element, that's a compiler error since the list doesn't necessarily support that particular type.

Spring Boot Custom Query In Controller

How do i add a custom query to my Spring boot application and access it in the controller?
I have two tables called CarBrand and YearMade. CarBrand has ID, code and Brand as columns. YearMade also has ID, code and year as columns.
I have written my model classes with setter and getter methods for each entity. I have added my repository interfaces and my service classes.
public interface YearRepository extends JpaRepository<Year, Long> {
}
My Brand Repository
public interface BrandRepository extends JpaRepository<Brand, Long> {
#Query("select b from brand b where brand.brand = ?1")
List<Brand> findVehicleBrand(String brand);
}
Here is my service class
public class YearService {
#Autowired
private YearRepository yearRepository;
public List<Year> listAll(){
return yearRepository.findAll();
}
public void save(Year engineSize){
yearRepository.save(engineSize);
}
public Year get (long id){
return yearRepository.findById(id).get();
}
public void delete (Long id){
yearRepository.deleteById(id);
}
}
My Brand Service
public interface BService {
List<Brand> findVehicleBrand(String name);
}
And this.
#Service
#Transactional
public class BrandService implements BService{
#Autowired
private BrandRepository brandRepository;
public List<Brand> listAll(){
return brandRepository.findAll();
}
public void save(Brand brand){
brandRepository.save(brand);
}
public Brand get (long id){
return brandRepository.findById(id).get();
}
public void delete (Long id){
brandRepository.deleteById(id);
}
#Override
public List<Brand> findVehicleBrand(String name) {
var brand = (List<Brand>) brandRepository.findVehicleBrand(name);
return brand;
}
}
In my controller, I get a path variable with a string, i use substring to break the string into two. The two substrings have the code for brand and year. The first two represent the year and the other three represent the brand. How do i compare the codes to the codes in the database to get the actual year and brand.
http://localhost:8081/vincode/wwQPT
The ww is the code for the year 1990 and QPT is for Honda Motor Company in the database.
I want a JSON response like this
{
Year Made : 1990,
Brand Name : Honda Motor Company
}
Here is the controller class i have so far.
#RequestMapping("/{vincode}")
public #ResponseBody String getAttr(#PathVariable(value="vincode") String vincode) {
String yr = vincode.substring(0,1);
String brand = vincode.substring(2,4);
System.out.println(yr);
return yr;
}
Where do i add the query and how do i use it in my controller?
Thank you.
If you dont have request mappong wlth value top of the class then http://localhost:8081/vincode/ww/QPT
RequestMapping("/vincode/{code}/{company}") can be more useful
There is no need to use substring maybe code or company key sizes changes.
Also service layer can be injected and used anytime.
Firstly add this statement in BrandRepository interface :
public interface BrandRepository extends JpaRepository<Brand, Long> {
#Query("select b from brand b where brand.brand = ?1")
List<Brand> findVehicleBrand(String brand);
public Brand findByCode(String code);
}
In YearRepository interface :
public interface YearRepository extends JpaRepository<Year, Long> {
public Year findByCode(String code);
}
Then add this method in BrandService Class:
public String findByCode (String code){
return brandRepository.findByCode(code).getBrand();
}
Then add this method in YearService Class:
public String findByCode (String code){
return yearRepository.findByCode(code).getYear;
}
Create Domain Class :
public class YearBrand
{
private String YearMade;
private String BrandName;
public YearBrand(String year, String brand)
{
this.YearMade=year;
this.BrandName=brand;
}
}
Then In Controller Class :
#RequestMapping("/{vincode}")
public YearBrand getAttr(#PathVariable(value="vincode") String vincode) {
String yr = vincode.substring(0,1);
String brand = vincode.substring(2,4);
return new YearBrand(yearService.findByCode(yr),brandService.findByCode(brand));
}
NOTES:
Make sure your Controller Class is annotated with #RestController
Spring Data JPA derives queries based on method naming conventions.
So, to get year by code in YearMade table, you need to modify your YearReporsitory interface like this (add an abstract method):
public interface YearRepository extends JpaRepository<Year, Long> {
// set return type as required
//find - Do What, ByCode - Criteria.
public Integer findByCode(String code);
}
And, use this method in your YearService just as you've used other methods.
But, you cannot use the same method for getting brand by code requirement. You'll have to write a repo class for it like:
public interface BrandRepository extends JpaRepository<CarBrand, Long> {
public Integer findByCode(String code);
}
You can write these methods for all the members of your Entity class. You've to follow the naming convention to get Spring recognize it.
EDIT (to show how to use this in controller and service class):
YearRepository interface:
public interface YearRepository extends JpaRepository<Year, Long> {
// set return type as required
//find - Do What, ByCode - Criteria.
public Integer findByCode(String code);
}
BrandRepository
public interface BrandRepository extends JpaRepository<Brand, Long> {
/*The below two methods are abstract methods.*/
// it must follow the findby<MemberName> convention
//return CarBrand
CarBrand findByBrand(String brand);
/*return a CarBrand Entity*/
public CarBrand findByCode(String code);
YearService:
public class YearService {
#Autowired
private YearRepository yearRepository;
public List<Year> listAll() {
return yearRepository.findAll();
}
public void save(Year engineSize) {
yearRepository.save(engineSize);
}
public Year get(long id) {
return yearRepository.findById(id).get();
}
public void delete(Long id) {
yearRepository.deleteById(id);
}
public int getYearByCode(String code) {
//here, we're using this method just as you've used the methods above.
//Spring constructs the query at runtime
return yearRepository.findByCode(code); //<-- usage of the custom method
}
}
BService:
public interface BService {
CarBrand findVehicleBrand(String name);
}
BrandService:
#Service
#Transactional
public class BrandService implements BService{
#Autowired
private BrandRepository brandRepository;
public List<Brand> listAll(){
return brandRepository.findAll();
}
public void save(Brand brand){
brandRepository.save(brand);
}
public Brand get (long id){
return brandRepository.findById(id).get();
}
public void delete (Long id){
brandRepository.deleteById(id);
}
#Override
public CarBrand findVehicleBrand(String name) {
//var brand = (List<Brand>) brandRepository.findVehicleBrand(name);
var brand = brandRepository.findByBrand(name); //<-- using the custom method in brandRepository
return brand;
}
}
Your RepsonseDto:
class RepsonseDto {
private String yearMade;
private brandName;
//getters and setters
/*Use #JsonProperty("Year Made") and #JsonProperty("Brand Name") on your getters. Otherwise, you will get json reposnse as: "yearMade" and "brandName"*/
}
Controller:
There are better ways to write controllers and inject dependencies. Let's keep it simple for now.
#RequestController
class YourController {
//inject dependencies
#Autowired
YearService yearService;
#Autowired
BrandService brandService;
#RequestMapping("/{vincode}")
// the definition for ResponseEntity is above
public ResponseEntity<RepsonseDto> getAttr(#PathVariable(value="vincode") String vincode) {
// create a ReponseEntity object
RepsonseDto retEntity = new RepsonseDto();
// do a check for null and expected length of vincode
if(vincode != null && vincode.length() == 5) {
String yr = vincode.substring(0,1);
String brand = vincode.substring(2,4);
retEntity.setYearMade(yearService.getYearByCode(yr));
retEntity.setBrandName(brandService.findVehicleBrand(brand));
System.out.println(yr);
}
return new ResponseEntity<>(retEntity, HttpStatus.OK)
}
NOTE: I didn't use an IDE to write this. There may be compiler errors. Hope this gives you an idea of it all fits in.

java - Access child property from parent function/scope

I'm coming from PHP and moved to java. I'm asking myself (and you guys) if there is a way to implement someting like this:
I'm trying to implement a class/classes to create CRUD operations for many database entities. All entities inherit their functions (most of them from the parent)
I need to implement the tableName and idFieldName in the parent class DatabaseEntity to avoid compiler warnings.
It seems like java tries to use the parents properties (which are obviously null) because the function is implemented in the parent.
Is there a way to overcome this problem? Any feedback is greatly apreciated!
abstract class DatabaseEntity {
protected String tableName;
protected String idFieldName;
public DataRecord readFromDB(int recordID) throws SQLException {
...
String sqlStatement = String.format("SELECT * FROM %s WHERE %s = %s", this.tableName, this.idFieldName, recordID); // Exception shows this line
...
}
}
class DatabaseRecord extends DatabaseEntity {
protected String tableName = "DatabaseRecordTable";
protected String idFieldName = "ID";
public void getRecord() {
...
DataRecord record = this.readFromDB(1); // leads to java.lang.NullPointerException: null
...
}
}
Disclaimer: I'm new to github and I apreciate any feedback on improoving my posts :)
when you use the method readFromDBin which you refer to the tableNameand the idFieldName, these two fields remain nullas long as they are not initailized,
try to remove the fields from your abstract class and do something like this :
abstract class DatabaseEntity {
// protected String tableName;
// protected String idFieldName;
public abstract String getTableName();
public abstract String getIdFieldName() ;
public DataRecord readFromDB(int recordID) throws SQLException {
...
String sqlStatement = String.format("SELECT * FROM %s WHERE %s = %s",getTableName(), getIdFieldName(), recordID);
...
}
}
and the implementation would be like :
class DatabaseRecord extends DatabaseEntity {
protected String tableName = "DatabaseRecordTable";
protected String idFieldName = "ID";
public void getRecord() throws SQLException {
DataRecord record = this.readFromDB(1);
}
#Override
public String getTableName() {
return this.tableName;
}
#Override
public String getIdFieldName() {
return this.idFieldName ;
}
}

Suggestions on how to create a changewatcher on a SlingModel to enable persistence to the JCR

We are currently attempting to implement an extension to SlingModels, to allow a slingmodel to be persisted to the JCR directly.
Our strategy has 2 considered starting conditions:
1. A new object that is to be persisted
2. An object that has been retrieved from the JCR, altered, and is then to be persisted again
For situation 1, we are using reflection to examine the object, create a new node for the model, insert properties for any of the primitive variables found, and recursively use the same persistence approach for any complex model objects found as variables, and collections.
My question on best approach relates to situation 2. If we pull out an object from the repository, we cannot be guaranteed that the node will not be synchronously changed in the meantime. Thus, we would like to implement a change watcher on the SlingModel that keeps a transaction journal on any changes made. The transactions can then be used to set the relevant properties when persisting the object back to the JCR again.
I have considered using an observer pattern, but this would mean that we would need to implement a function within the setter on each SlingModel, which is not ideal at all, as it requires a developer to remember to add the code and do it correctly.
Ideally, I would like to implement something like an interceptor directly on the variable, or if not possible, on the setter itself, and mandate that each model would then need to use a getter/setter for each variable. We can configure code scanning tools to enforce developers to implement getter/setters.
What would the be the best way to approach the change watcher here?
import java.util.List;
public class Teacher {
private String userName;
private String cource;
private List<Student> students;
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getCource() {
return cource;
}
public void setCource(String cource) {
this.cource = cource;
}
}
public class Student {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class ClassFacadeCglib implements MethodInterceptor{
private Object target;
public Object getInstance(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
// callback method
enhancer.setCallback(this);
// create proxy object
return enhancer.create();
}
#Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
if(method.getName().startsWith("set")){
System.out.println(method.getName()+" start");
proxy.invokeSuper(obj, args);
System.out.println(method.getName()+" end..");
}
if(method.getName().startsWith("get")){
System.out.println(method.getName()+" start");
proxy.invokeSuper(obj, args);
System.out.println(method.getName()+" end");
}
return null;
}
}
public class Main {
public static void main(String[] args) {
ClassFacadeCglib cglib=new ClassFacadeCglib();
Teacher teacher=(Teacher)cglib.getInstance(new Teacher());
teacher.setCource("Math");
teacher.getUserName();
}
}
Note :
cglib-full-2.0.2.jar is required for running.
see https://repo1.maven.org/maven2/cglib/cglib-full/2.0.2/

Handling Queries for Multiple Tables

I am working on a project that utilizes a database with several relations. We are working with tables such as:
Customers(id, f_name, l_name)
CreditCards(cardNum, expDate, securityCode)
BillingInfo(id, f_name, l_name, address, city, zip)
etc...
Using Java Database Connectivity, my question is, is there a common way one performs queries on these relations?
Even before getting to the "guts" of this project, I envision being able to call some method void insert(int id, String f_name, String l_name), a member method of a hypothetical CustomerQueryHandler class. This class would of course be accompanied by other methods such as a delete and update method.
I figured I'd start with an abstract class called QueryHandler:
import java.sql.*;
public abstract class QueryHandler {
protected String jdbcUrl = null;
protected String userid = null;
protected String password = null;
protected Connection conn;
QueryHandler(String url_in, String id_in, String pass_in) {
this.jdbcUrl = url_in;
this.userid = id_in;
this.password = pass_in;
try {
this.ds = new OracleDataSource();
} catch (SQLException e) {
e.printStackTrace();
}
ds.setURL(this.jdbcUrl);
try {
conn = ds.getConnection(userid, password);
} catch (SQLException e) {
e.printStackTrace();
}
}
public abstract void insert(/*not sure of signature*/);
public abstract void update(/*not sure of signature*/);
public abstract void delete(/*not sure of signature*/);
/* OTHER METHODS BELOW */
}
There would be a derived class for each table and each derived class would implement its own version of insert, update, and delete:
public class CustomersQueryHandler extends QueryHandler {
public CustomersQueryHandler(String url_in, String id_in, String pass_in) {
super(String url_in, String id_in, String pass_in);
}
...
This is actually the point where I became very confused because, does it make sense for this to be a superclass, even though each subclass will have its own parameter list for the aforementioned methods?

Categories

Resources