Let's say I want to mock a class with the following structure, for testing purposes:
#Data
public class Street() {
private House house;
#Data
static class House {
private List<Room> rooms;
}
#Data
static class Room {
private Door door;
}
#Data
static class Door {
private String material;
}
}
What would be the best way to concisely create a Street object, containing a House that has a Room with a wooden door?
I was thinking of adding a Lombok #Builder annotation to the Street class, but discovered I would also need builders for each of the nested classes, and was wondering if there would be a cleaner way to achieve this.
Use #SuperBuilder from lombok project
Assume you have :
#Getter
#SuperBuilder
public class Parent {
private final String parentName;
private final int parentAge;
}
#Getter
#SuperBuilder
public class Child extends Parent {
private final String childName;
private final int childAge;
}
#Getter
#SuperBuilder
public class Student extends Child {
private final String schoolName;
}
Then you can create a new Student like this :
Student student = Student.builder()
.parentName("Andrea")
.parentAge(38)
.childName("Emma")
.childAge(6)
.schoolName("Baeldung High School")
.build();
Reference : https://www.baeldung.com/lombok-builder-inheritance#lombok-builder-and-inheritance-1
My only suggestion is this:
public class Street {
private House house;
private Room room;
private Door door;
public class House{
//build class House
}
public class Room{
//build class Room
}
public class Door{
//build class Door
}
public Street(House house, Room room, Door door) {
this.house = new House();
this.room = new Room();
this.door = new Door();
}
}
and then you can work inside the Street class with the objects you have to access methods of the other little classed nested into Street
Related
I would like to fill this fields with mapstruct but i don't know how to fix it because i never use mapstruct with generic type thanks for any attentions
#Data
#ToString
public class SvGateRequest<T> {
public SvGateRequest(String method, T params) {
this.method = method;
this.params = params;
}
private String jsonrpc="2.0";
private String method;
private Long id = System.currentTimeMillis();
private T params;
#Data
#ToString
#Builder
#DynamicUpdate
#DynamicInsert
public static class CardNew{
private Card card;
private CardVerify otp;
#Data
#ToString
#Builder
public static class Card{
private String pan;
private String expiry;
}
#Data
#ToString
#Builder
public static class CardVerify{
private Long id;
private String code;
}
}
}
it is my dto class which take params to fill FillCard class but sometimes instead of FillCard class i can use fill CardVerify class with another dto class thats why i try optimize my code
#Data
#JsonInclude(JsonInclude.Include.NON_NULL)
public class FillCard {
private String pan;
private String expiry;
}
whether it is preferable to use generic types with mapstruct itself or not
#Data
#Builder
public class ClassA {
private ClassB b;
private String createdBy;
private class ClassB {
String name;
int version;
}
}
Hi I want to create ClassA in another java file this way:
ClassA.builder().createdBy("Alex")
.b(ClassB.builder()
.name("Game")
.version(2).build())
.build();
Is this possible for private class classB?
Thx
I recommend as below:
#Data
#Builder
public class ClassA {
private ClassB b;
private String createdBy;
#Builder
#Data
static class ClassB {
String name;
int version;
}
}
if you want unvisible ClassB it is impossible. and To using #Builder on inner class , class must be static class
private modifier means that the variable is only visible for this class only. So if you create private class B inside class A it means B only visible for A.
As #sweeper said in the comment, you cannot use class B in another file / class except for class A.
If you still want to use that way, you can create class B independently.
ClassA.class
#Data
#Builder
public class ClassA {
private ClassB b;
private String createdBy;
}
ClassB.class
#Data
#Builder
class ClassB {
String name;
int version;
}
Let's have example base class
#Data
#NoArgsConstructor
#AllArgsConstructor
public class User {
#JsonProperty("login")
private String login;
#JsonProperty("password")
private String password;
#JsonProperty("additionalData")
private String additionalData;
}
and second one that extends User class
#Data
#NoArgsConstructor
#AllArgsConstructor
public class EnhancedUser extends User {
#NotNull
#JsonProperty("additionalData")
private String additionalData;
}
I but It doesn't work because when I create instance of EnhancedUser class field additionalData can be null.
Any idea?
Look:
public class Sample {
public static void main(String[] args) {
EnhancedUser enhancedUser = new EnhancedUser();
enhancedUser.setAdditionalData("TAMU");
enhancedUser.setLogin("ANY");
enhancedUser.setPassword("ANY");
System.out.println(enhancedUser);
System.out.println(enhancedUser.getAdditionalData());
}
#Data
#NoArgsConstructor
#AllArgsConstructor
public static class User {
private String login;
private String password;
private String additionalData;
}
#EqualsAndHashCode(callSuper = true)
#Data
#NoArgsConstructor
#AllArgsConstructor
#ToString(callSuper = true)
public static class EnhancedUser extends User {
#NotNull
private String additionalData;
}
}
And the result of printlnis
Sample.EnhancedUser(super=Sample.User(login=ANY, password=ANY, additionalData=TAMU), additionalData=TAMU)
TAMU
You do realize that you actually have 2 fields "additionalData"? Since you can't override fields but merely hide them. And this is a huge nono anti-pattern in general.
Either you rename your field or you think of a more approriate implementation, like implementing this logic yourself with and a constructor argument and a call of the additionalData setter from your constructor.
I have designed my database to use the inheritance strategy of Table Per Class where the common fields exists in the derived tables as well as in the parent table. Some simple model would look like this.
Vehicle.java
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Vehicle {
#Id #GeneratedValue
private int id;
private String name;
private String brand;
}
Car.java
#Entity
public class Car extends Vehicle {
private String oil;
}
Bike.java
#Entity
public class Bike extends Vehicle {
private String frame;
}
Now, I would like to have a unified VehicleRepository for all kinds of Vehicle objects, including Car and Bike.
The repository could look something like this.
VehicleRepository.java
#Repository
public interface VehicleRepository extends CrudRepository<Vehicle, Integer> {
#Query("SELECT v FROM Vehicle e WHERE v.vehicleId = ?1")
public Vehicle findById(Integer vehicleId);
}
So I'd like to be able to do something like following.
int carId = 3; // I know that in the DB there's a car with that ID
int bikeId = 7; // I know that in the DB there's a bike with that ID
// the important part
Car car = (Car) repo.findById(carId);
Bike bike = (Bike) repo.findById(bikeId);
// now I want to be able to call:
car.getOil();
bike.getFrame();
The question is: would this work and is this a good pattern to do it?
You can include all the fields in the Vehicle and try to use projections for Car and Bike.
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Vehicle {
#Id #GeneratedValue
private int id;
private String name;
private String brand;
private String oil;
private String frame;
}
For Car and Bike you can use projections:
public interface VehicleProjection {
public int getId();
public String getBrand();
public String getName();
}
public interface Car extends VehicleProjection {
public String getOil();
}
public interface Bike extends VehicleProjection {
public String getFrame();
}
And your repository should look like this:
public interface CarRepository extends Repository<Vehicle, Integer> {
public Car findById(Integer carId);
}
Same for Bike repository
Let's have source classes
#Data
public class Source {
private String name;
}
#Data
public class SourceParent {
private String parentName;
}
and target classes
#Data
public class Target {
private String name;
private TargetParent parent;
}
#Data
public class TargetParent {
private String parentName;
}
As you can see in Source I don't have the parent reference.
What I do is
Source s = findSource();
SourceParent sp = findParentForSource(s);
Target t = mapperFactory.map(s, Target.class);
mapperFactory.map(sp, t); //<--- Here is the problem
The problem is that I cannot map a SourceParent object to a specific field in Target.
I know how to do this using custom mappers or another "manual" ways. Is there a way to do it "Orika way"?
Something like:
mapperFactory.classMap(SourceParent.class, Target.class)
.fieldAtoB("?myslef?","parent")
.register();
Try with
mapperFactory.classMap(SourceParent.class, Target.class)
.fieldAtoB("","parent")
.register();