Linked entities (OneToMany) not shown in Play2 Java form - java

I'm having trouble with a Play! 2 form in which an object (a member of a neighbourhood association) containing two Lists (of persons in the household and of bank accounts) is edited. Weirdly, the list of persons is properly shown in the form while the textInputs of the bank accounts are empty in the form. The number of bank accounts is correct, though.
I added some debug statements in the edit form template to display the contents of the fields. For the field related to the list of Persons, it shows
BeanList size[2] hasMoreRows[false] list[models.Persoon#1, models.Persoon#2]
while for the list of bank accounts it shows
BeanList deferred
I've cut down the app as much as possible to isolate the issue, and pushed the code to Github (git://github.com/janpascal/ledenadmin.git) on branch debug-form. It seems both lists are created and handled exactly the same, but somehow show up differently. The relation is Cascade-ALL. Just to make sure I've tried adding save() and update() calls when creating the Person or Bankrekening objects, but that doesn't make a difference.
Any help is greatly appreciated!
The form:
#(id: Long, myForm: Form[Lid])
#main("Bewerk lid") {
<h1>Bewerk lid</h1>
#myForm
<br>
#myForm.value()
<br>
#myForm.field("personen").value()
<br>
#myForm.field("rekeningnummers").value()
<br>
#helper.form(action = routes.Leden.saveLid(id)) {
<fieldset>
<legend>Lid #id</legend>
#helper.repeat(myForm("personen"), min = 1) { persoonField =>
#helper.inputText(persoonField("name"), '_label -> "Naam" )
}
#helper.inputText(myForm("address"), '_label -> "Adres")
#helper.repeat(myForm("rekeningnummers"), min = 1) { rekeningField =>
#helper.inputText(rekeningField("rekeningnummer"))
}
</fieldset>
<input type="submit" value="Opslaan">
}
}
My models:
#Entity
public class Lid extends Model {
#GeneratedValue(strategy=GenerationType.AUTO, generator="lid_seq_gen")
#SequenceGenerator(name="lid_seq_gen", sequenceName="LID_SEQ")
#Id
public Long id;
#OneToMany(cascade=CascadeType.ALL, mappedBy="lid")
public List<Persoon> personen;
public String address;
#OneToMany(cascade=CascadeType.ALL, mappedBy="lid")
public List<Bankrekening> rekeningnummers;
public Lid(Long id, String name, String address, String bankaccount) {
this.id = id;
this.personen = new ArrayList<Persoon>();
this.personen.add(new Persoon(this, name));
this.rekeningnummers = new ArrayList<Bankrekening>();
this.rekeningnummers.add(new Bankrekening(this,bankaccount));
this.address = address;
}
public String toString() {
return "Lid "+id+" ("+getFirstName()+")";
}
public String getFirstName() {
if(personen.size()>=1) return personen.get(0).name;
return "";
}
public Bankrekening addRekening(String rekeningnummer) {
Bankrekening rek = new Bankrekening(this, rekeningnummer);
rekeningnummers.add(rek);
return rek;
}
public static void create(Lid lid) {
lid.save();
}
public static void delete(Long id) {
find.ref(id).delete();
}
public static Finder<Long,Lid> find = new Finder<Long, Lid>(
Long.class, Lid.class
);
}
#Entity
public class Persoon extends Model {
#GeneratedValue(strategy=GenerationType.AUTO, generator="persoon_seq_gen")
#SequenceGenerator(name="persoon_seq_gen", sequenceName="PERSOON_SEQ")
#Id
public Long id;
#ManyToOne
public Lid lid;
#Constraints.Required
public String name;
public Persoon(Lid lid, String name) {
this.lid = lid;
this.name = name;
}
public static void create(Persoon p) {
p.save();
}
public static void delete(Long id) {
find.ref(id).delete();
}
public static Finder<Long,Persoon> find = new Finder<Long, Persoon>(
Long.class, Persoon.class
);
}
#Entity
public class Bankrekening extends Model {
#GeneratedValue(strategy=GenerationType.AUTO, generator="bankrek_seq_gen")
#SequenceGenerator(name="bankrek_seq_gen", sequenceName="BANKREKENING_SEQ")
#Id
public Long id;
#ManyToOne
public Lid lid;
#Constraints.Required
public String rekeningnummer;
public Bankrekening(Lid lid, String nummer) {
this.lid = lid;
this.rekeningnummer = nummer;
}
public static void create(Bankrekening bankrekening) {
bankrekening.save();
}
public static void delete(Long id) {
find.ref(id).delete();
}
public static Finder<Long,Bankrekening> find = new Finder<Long, Bankrekening>(
Long.class, Bankrekening.class
);
}
The controller:
public class Leden extends Controller {
public static Result lijst() {
List<Lid> leden = Lid.find.all();
return ok(ledenlijst.render(leden));
}
public static Result bewerkLid(Long id) {
Form<Lid> myForm = form(Lid.class).fill(Lid.find.byId(id));
Lid lid = Lid.find.byId(id);
System.out.println("Editing "+lid.toString());
System.out.print("Bankrekeningen:");
for(Bankrekening rek: lid.rekeningnummers) {
System.out.print(" "+rek.rekeningnummer);
}
System.out.println();
System.out.println("Form information:");
System.out.println(myForm.value());
System.out.println(myForm);
System.out.println(myForm.data());
return ok(editlid.render(id, myForm));
}
public static Result saveLid(Long id) {
Form<Lid> form = form(Lid.class).bindFromRequest();
if(form.hasErrors()) {
return badRequest(editlid.render(id,form));
}
form.get().update(id);
System.out.println("Form information:");
System.out.println(form.value());
System.out.println(form);
System.out.println(form.data());
Lid lid = form.get();
System.out.println("Updating"+lid.toString());
System.out.print(" Bankrekeningen:");
for(Bankrekening rek: lid.rekeningnummers) {
System.out.print(" "+rek.rekeningnummer);
}
return lijst();
}
}
And finally the Global object seeding the database:
public class Global extends GlobalSettings {
#Override
public void onStart(Application app) {
InitialData.insert(app);
}
static class InitialData {
public static void insert(Application app) {
if(Ebean.find(Lid.class).findRowCount() == 0) {
System.out.println("Seeding members");
for(long i=1; i<10; i++) {
Lid lid = new Lid(i, "lid"+i, "Kerkstraat "+i, "Bank account"+i);
//lid.addRekening(new Long(i*5462).toString());
Lid.create(lid);
}
}
}
}
}

This was caused by a dirty Play project somehow, at least cleaning up both the Play installation and the project itself helped.

Related

System Security - Manually Identifying Vulnerabilities

Refer to the seven security areas outlined in the Vulnerability Assessment Process Flow Diagram. Use what you’ve learned in steps 1 and 2 to guide your manual review. Identify all vulnerabilities in the Project One Code Base, linked in Supporting Materials, by manually inspecting the code. Document your findings in your vulnerability assessment report. Be sure to include a description that identifies where the vulnerabilities are found (specific class file, if applicable).
Vulnerability Process Flow Diagram
#SpringBootApplication
public class RestServiceApplication {
public static void main(String[] args) {
SpringApplication.run(RestServiceApplication.class, args);
}
}
public class myDateTime {
int mySecond;
int myMinute;
int myHour;
int[] retrieveDateTime() {
/* implement accessor method */
return new int[3];
}
void setMyDateTime(int seconds, int minutes, int hour) {
/* implement accessor method */
}
}
#RestController
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
#GetMapping("/greeting")
public Greeting greeting(#RequestParam(value = "name", defaultValue = "World") String name) {
return new Greeting(counter.incrementAndGet(), String.format(template, name));
}
}
public class Greeting {
private final long id;
private final String content;
public Greeting(long id, String content) {
this.id = id;
this.content = content;
}
public long getId() {
return id;
}
public String getContent() {
return content;
}
}
public class customer {
private int account_number;
int account_balance;
public int showInfo() {
//code to show customer information
return this.account_number;
}
public void deposit(int a) {
account_balance = account_balance + a;
}
}
#RestController
public class CRUDController {
#RequestMapping("/read")
public CRUD CRUD(#RequestParam(value="business_name") String name) {
DocData doc = new DocData();
return new CRUD(doc.toString());
}
}
public class CRUD {
private final String content;
private final String content2;
public CRUD(String content) {
this.content = content;
this.content2 = content;
}
public CRUD(String content1, String content2) {
this.content = content1;
this.content2 = content2;
}
public String getContent() {
return content;
}
public String getContent2() {
return content2;
}
}
Honestly, I am just confused about what I am doing and looking for in the code for it to be classified as a vulnerability. Anything helps, thanks.

SDN4 is not returning nested Entities

Hello Stack overflow,
I have the following Problem:
I have these entity classes:
public class UnknownEntity extends NetworkEntity{
#Id
#GeneratedValue(strategy = UuidStrategy.class)
private String id;
#Override
public void setId(String id) {
this.id = id;
}
#Override
public String getId() {
return id;
}
}
#NodeEntity
public class NetworkEntity {
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#Id
protected String id;
public List<NetworkInterfaceEntity> getInterfaces() {
return interfaces;
}
public void setInterfaces(List<NetworkInterfaceEntity> interfaces) {
this.interfaces = interfaces;
}
#Relationship(type = "is_composed_of")
protected List<NetworkInterfaceEntity> interfaces ;
}
#NodeEntity
public class NetworkInterfaceEntity {
public String getInterfaceId() {
return interfaceId;
}
public void setInterfaceId(String interfaceId) {
this.interfaceId = interfaceId;
}
public String getIpAddress() {
return ipAddress;
}
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}
public String getNetmask() {
return netmask;
}
public void setNetmask(String netmask) {
this.netmask = netmask;
}
public String getMacAddress() {
return macAddress;
}
public void setMacAddress(String macAddress) {
this.macAddress = macAddress;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public InterfaceState getState() {
return state;
}
public void setState(InterfaceState state) {
this.state = state;
}
public List<NetworkInterfaceEntity> getSubInterfaces() {
return subInterfaces;
}
public void setSubInterfaces(List<NetworkInterfaceEntity> subInterfaces) {
this.subInterfaces = subInterfaces;
}
public long getBytesSent() {
return bytesSent;
}
public void setBytesSent(long bytesSent) {
this.bytesSent = bytesSent;
}
public long getBytesRecived() {
return bytesRecived;
}
public void setBytesRecived(long bytesRecived) {
this.bytesRecived = bytesRecived;
}
#Id
private String interfaceId;
private String ipAddress;
private String netmask;
private String macAddress;
private String name;
private InterfaceState state;
#Relationship(type = "is_composed_of")
private List<NetworkInterfaceEntity> subInterfaces;
private long bytesSent;
private long bytesRecived;
}
When I now try to query the UnknownEntities via a Neo4j Crud Repository with a custom #Query Method, the UnknownEntities wont be nested with the necessary NetworkInterfaceObjects, even tough my query returns these.
public interface UnknownEntityRepository extends CrudRepository<UnknownEntity,String> {
#Query("MATCH (u:UnknownEntity)-[:is_composed_of]->(i:NetworkInterfaceEntity) WHERE i.ipAddress IN {0} WITH u as unknown MATCH p=(unknown)-[r*0..1]-() RETURN collect(unknown),nodes(p),rels(p)")
List<UnknownEntity> searchMachinesByIp(List<String> ipAddresses);
}
In this particular case the NetworkInterfaceEntities do not contain more subInterfaces, so I only want the NetworkInterfaceEntities that belong the the UnknownEntity. But when I use this Query I only get UnknownEntities where the NetworkInterfaceList is null. I even tried different Querys to no avail for example:
"MATCH p=(u:UnknownEntitie)-[:is_composed_of]-(n:NetworkInterfaceEntity) WHERE n.ipAddress in {0} RETURN collect(n),nodes(p),rels(p)".
My Question is, if what I want is even possible with SDN4 Data and if it is, how I can achieve this, Since my alternative is to query the database for every NetworkInterface separately, which I think is really ugly.
Any help would be much appreciated.
please try if returning the full path like this:
public interface UnknownEntityRepository extends CrudRepository<UnknownEntity,String> {
#Query("MATCH (u:UnknownEntity)-[:is_composed_of]->(i:NetworkInterfaceEntity) WHERE i.ipAddress IN {0} WITH u as unknown MATCH p=(unknown)-[r*0..1]-() RETURN p")
List<UnknownEntity> searchMachinesByIp(List<String> ipAddresses);
}
works for your. If not, try naming the objects in question, i.e. RETURN i as subInterfaces works for you.
Are you using Spring Data Neo4j 4 or 5? If you're on 4, consider the upgrade to 5 to be on a supported level.
Please let me know, if this helps.

Room #Insert does not insert all records

I am running into an issue where only 1 record is being inserted into my Room SQLite DB.
When I perform a getAll(); the result only returns 1 record.
FOUND ISSUE: Genre[] genres = gson.fromJson(jsonArray.toString(), Genre[].class);
This line above is setting all "gid" values to 0, and I am not sure how to change that.
Genre.java
#Entity(indices = {#Index(value = {"id", "name"}, unique = true)})
public class Genre {
#PrimaryKey
private int gid;
//#ColumnInfo(name = "id") By Default - No need to annotate
#NonNull
private int id;
private String name;
public int getGid() {
return gid;
}
public void setGid(int gid) {
this.gid = gid;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
GenreDao.java
#Dao
public interface GenreDao {
#Query("SELECT * FROM Genre")
LiveData<List<Genre>> getAll();
#Insert(onConflict = OnConflictStrategy.REPLACE) //If there is a conflict, replace the record.
void insertAll(Genre... genres);
}
GenreRepository.java
public class GenreRepository {
private final GenreDao genreDao;
public GenreRepository(GenreDao genreDao) {
this.genreDao = genreDao;
}
//Database Methods
public void insertAll(Genre... genres) {
AsyncTask.execute(() -> { //Same as new Runnable()
genreDao.insertAll(genres);
});
}
public LiveData<List<Genre>> getAll() {
return genreDao.getAll();
}
}
APIUtil.java - getGenres() Method
This class makes an API call, returns the proper results, converts the JSONArray to a Genre[]. I can successfully loop through the Genre[] and confirm 10+ results come back.
public static void getGenres(Context context) {
APIWrapper wrapper = new APIWrapper(context, API_KEY);
Parameters params = new Parameters();
params.addFields(GENRE_FIELDS);
params.addLimit("50");
wrapper.genres(params, new onSuccessCallback() {
#Override
public void onSuccess(JSONArray jsonArray) {
Gson gson = new Gson();
Genre[] genres = gson.fromJson(jsonArray.toString(), Genre[].class);
//Insert DB
AppDatabase db = AppDatabase.getAppDatabase(context);
GenreRepository genreRepository = new GenreRepository(db.genreDao());
genreRepository.insertAll(genres);
}
#Override
public void onError(VolleyError volleyError) {
Log.e("GENRES ERROR:", volleyError.toString());
}
});
}
GenreViewModel.java
public class GenreViewModel extends ViewModel {
private GenreRepository genreRepository;
public GenreViewModel(GenreRepository genreRepository) {
this.genreRepository = genreRepository;
}
public void insertAll(Genre... genres){
genreRepository.insertAll(genres);
}
public LiveData<List<Genre>> getAll(){
return genreRepository.getAll();
}
}
SearchFragment.java
This is where I am retrieving the database values. This for loop only returns 1 result.
AppDatabase db = AppDatabase.getAppDatabase(getActivity());
GenreRepository genreRepository = new GenreRepository(db.genreDao());
GenreViewModel genreViewModel = new GenreViewModel(genreRepository);
genreViewModel.getAll().observe(this, genres -> { //new Observer<List<Genre>>()
for(Genre g : genres){
Log.e("GENRE", g.getName());
}
});
public void insertAll(Genre... genres){
genreRepository.insertAll(genres);
}
here is your mistake , what you provide as method definition and what you provide at call. see you make some thing wrong.
Solution
void insertAll(List<T> obj);
you can try with convert your array to list and put above in definition
I had this problem too.
And Solved it this way.
The problem was that the id that comes from server was mongoId and String so I should create a int primary key and pass currentTime as value to it so the database can insert all of them not replace them.
But you should consider using System.nanoTime() method instead of System.currentTimeMillis() cause sometimes it generates same value and then room replace them instead of inserting each one of them.

Delete entity with Composite Key by Primary Key

I have 4 tables.
Country(id, name), CountryType(id, name), Client (id, name) and Country_CountryType_Client relation Table (country_id, countryType_id, client_id).
Here is my Country class:
#GeneratePojoBuilder(
intoPackage = "*.builder")
#Entity
#Table(name = "MD_COUNTRY")
#SequenceGenerator(
name = "SEQ_MD_COUNTRY",
sequenceName = "SEQ_MD_COUNTRY",
allocationSize = 1)
public class Country implements Serializable {
private static final long serialVersionUID = -3313476149373055743L;
private Long md_country_id;
private String nameKey;
private List<CountryCountryTypeClient> cCTypeClients;
#Id
#GeneratedValue(
generator = "SEQ_MD_COUNTRY")
#Column(
name = "MD_COUNTRY_ID")
public Long getMd_country_id() {
return md_country_id;
}
public void setMd_country_id(Long md_country_id) {
this.md_country_id = md_country_id;
}
#Column(name = "MD_COUNTRY_NAME_KEY")
public String getNameKey() {
return this.nameKey;
}
public void setNameKey(String name) {
this.nameKey = name;
}
#OneToMany(fetch=FetchType.EAGER,mappedBy="pk.country",cascade=CascadeType.ALL)
public List<CountryCountryTypeClient> getCountryCountryTypeClient() {
return cCTypeClients;
}
public void setCountryCountryTypes(List<CountryCountryTypeClient> countryCountryTypeClient) {
this.cCTypeClient = countryCountryTypeClient;
}
/* ... hashCode and equals methods..*/
The CountryType and Client classes look the same.
Here is my CountryCountryTypeClient class :
#GeneratePojoBuilder(
intoPackage = "*.builder")
#Entity
#Table(
name = "COUNTRY_COUNTRY_TYPE_CLIENT")
#AssociationOverrides({
#AssociationOverride(name= "pk.country",
joinColumns=#JoinColumn(name = "COUNTRY_ID")),
#AssociationOverride(name="pk.countryType",
joinColumns=#JoinColumn(name = "COUNTRY_TYPE_ID")),
#AssociationOverride(name="pk.client",
joinColumns=#JoinColumn(name = "CLIENT_ID"))
})
public class CountryCountryTypeClient implements Serializable{
private static final long serialVersionUID = -879391903880384781L;
private CountryCountryTypeClientPK pk = new CountryCountryTypeClientPK();
public CountryCountryTypeClient() {}
#EmbeddedId
public CountryCountryTypeClientPK getPk() {
return pk;
}
public void setPk(CountryCountryTypeClientPK pk) {
this.pk = pk;
}
#Transient
public Country getCountry(){
return getPk().getCountry();
}
public void setCountry(Country country) {
getPk().setCountry(country);
}
#Transient
public CountryType getCountryType(){
return getPk().getCountryType();
}
public void setCountryType(CountryType countryType) {
getPk().setCountryType(countryType);
}
#Transient
public Client getClient() {
return getPk().getClient();
}
public void setClient(Client client) {
getPk().setClient(client);
}
/* ... hashCode and equals ... */
Here is my CountryCountryTypeClientPK class :
#Embeddable
public class CountryCountryTypeClientPK implements Serializable {
private static final long serialVersionUID = -3934592006396010170L;
private Country country;
private CountryType countryType;
private Client client;
public CountryCountryTypeClientPK() {}
#ManyToOne
public Country getCountry() {
return country;
}
public void setCountry(Country country) {
this.country = country;
}
#ManyToOne
public CountryType getCountryType() {
return countryType;
}
public void setCountryType(CountryType countryType) {
this.countryType = countryType;
}
#ManyToOne
public Client getClient() {
return client;
}
public void setClient(Client client) {
this.client = client;
}
/*... hashCode and equals methods ..*/
My CountryCountryTypeClientRepository class :
public interface CountryCountryTypeRepository extends JpaRepository<CountryCountryTypeClient, CountryCountryTypeClientPK> {}
For my Country class I have CountryService class with saveCountry method :
public Country saveCountry(final Country dtoCountry) {
//save NEW Country
if(dtoCountry.getId()==null){
de.bonprix.global.masterdata.model.Country modelWithoutID = convertToModel(dtoCountry);
for (CountryCountryTypeClient cCTypeClient : modelWithoutID.getCountryCountryTypeClients()) {
cCTypeClient.setCountry(modelWithoutID);
}
return convertToDTO(this.countryRepository.saveAndFlush(modelWithoutID));
}
//save EDITED Country
else if (!(dtoCountry.getId()==null)){
de.bonprix.global.masterdata.model.Country modelWithID = convertToModel(dtoCountry);
for (CountryCountryTypeClient cCTypeClient : modelWithID.getCountryCountryTypeClients()) {
cCTypeClient.setCountry(modelWithID);
ccTypeClientRepository.delete(cCTypeClient);
}
return convertToDTO(this.countryRepository.saveAndFlush(modelWithID));
}
return null;
}
The question is: How can I delete all rows from my Country_CountryType_Client Table by Country_ID. Not by PK, but by Country_ID.
When I am saving the country in my Country Table, the Country_CountryType_Client is automatically updated with corresponding values.
Small example, just to clear the current problem.
In my Country_CountryType_Client Table now I have this.
And now I want to save the NewCountry that has all the same relation except the last row (298-2-9). My NewCountry dont know nothing about (298-2-9 relation). Before saving I have to delete all rows that have 298 id.
Hope the problem is clear.
I don't really understand the issue. Seems like all you really want to do is remove a single CountryCountryTypeClient from the Country with identifier 298.
Therefore if you were to update your mapping in as outlined in the following:
https://docs.oracle.com/cd/E19798-01/821-1841/giqxy/
#OneToMany(fetch=FetchType.EAGER,mappedBy="pk.country",cascade=CascadeType.ALL, orphanRemoval = true)
public List<CountryCountryTypeClient> getCountryCountryTypeClient() {
return cCTypeClients;
}
You can then simply do as follows:
Country country = // the country with id 298
CountryCountryTypeClient client = // the client with id 298/2/9
country.getCountryCountryTypeClient().remove(client);
countryRepository.save(country);

Spring Data JPA - Get the values of a non-entity column of a custom native query

I am using Spring Boot/MVC.
I have a custom query using JpaRepository:
public interface WorkOrderRepository extends JpaRepository<WorkOrder, Integer> {
#Query(value = "SELECT * FROM (SELECT * FROM workorder) Sub1 INNER JOIN (SELECT wo_number, GROUP_CONCAT(service_type SEPARATOR ', ') AS 'service_types' FROM service_type GROUP BY wo_number) Sub2 ON Sub1.wo_number=Sub2.wo_number WHERE fleet_company_id=?1 AND (order_status='On-Bidding' OR order_status='Draft')", nativeQuery = true)
Collection<WorkOrder> findWorkOrdersByFleet(Long fleetCompanyID);
}
It returns the following table:
http://imgur.com/Ylkc6U0
As you can see it has service_types columns which is a result of Concat, it's not part of the entity class. My problem is how can I get the value of that column. Some said I can use a separate DTO to map the service_types column? Or I can use 'new' keyword? Maybe you have other worked on me. I also tried to make a transient column service_types but it didn't work.
This is my entity class:
#Entity
#Table(name="workorder")
public class WorkOrder {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="wo_number")
private Long woNumber;
#ManyToOne(optional=false, cascade=CascadeType.ALL)
#JoinColumn(name = "vehicle_id")
private Vehicle vehicle;
#ManyToOne(optional=false, cascade=CascadeType.ALL)
#JoinColumn(name = "fleet_company_id")
private FleetCompany fleetCompany;
#Column(name="order_title")
private String orderTitle;
#Column(name="order_date")
private String orderDate;
#Column(name="order_time")
private String orderTime;
#Column(name="order_status")
private String orderStatus;
#Column(name="ref_number")
private String refNumber;
#Column(name="proposals")
private int proposals;
//#Column(name="serviceTypes")
#Transient
private int serviceTypes;
public WorkOrder() {
super();
}
public Long getWoNumber() {
return woNumber;
}
public void setWoNumber(Long woNumber) {
this.woNumber = woNumber;
}
public String getOrderTitle() {
return orderTitle;
}
public void setOrderTitle(String orderTitle) {
this.orderTitle = orderTitle;
}
public String getOrderDate() {
return orderDate;
}
public void setOrderDate(String orderDate) {
this.orderDate = orderDate;
}
public String getOrderTime() {
return orderTime;
}
public void setOrderTime(String orderTime) {
this.orderTime = orderTime;
}
public String getOrderStatus() {
return orderStatus;
}
public void setOrderStatus(String orderStatus) {
this.orderStatus = orderStatus;
}
public String getRefNumber() {
return refNumber;
}
public void setRefNumber(String refNumber) {
this.refNumber = refNumber;
}
public int getProposals() {
return proposals;
}
public void setProposals(int proposals) {
this.proposals = proposals;
}
public Vehicle getVehicle() {
return vehicle;
}
public void setVehicle(Vehicle vehicle) {
this.vehicle = vehicle;
}
public FleetCompany getFleetCompany() {
return fleetCompany;
}
public void setFleetCompany(FleetCompany fleetCompany) {
this.fleetCompany = fleetCompany;
}
public int getServiceTypes() {
return serviceTypes;
}
public void setServiceTypes(int serviceTypes) {
this.serviceTypes = serviceTypes;
}
}
Some people told me to make a DTO:
public class WorkOrderDTO extends WorkOrder {
private String service_types;
public WorkOrderDTO() {
super();
}
public WorkOrderDTO(String service_types) {
this.service_types = service_types;
}
public String getService_types() {
return service_types;
}
public void setService_types(String service_types) {
this.service_types = service_types;
}
}
and add make the repository replaced from WorkOrder to WorkOrderDTO.
public interface WorkOrderRepository extends JpaRepository<WorkOrderDTO, Integer>
but when I do that I have autowiring problems.
I solved my own problem, finally!!!
I used #SqlResultMapping
SqlResultSetMapping(
name="workorder",
classes={
#ConstructorResult(
targetClass=WorkOrderDTO.class,
columns={
#ColumnResult(name="wo_number", type = Long.class),
#ColumnResult(name="service_types", type = String.class),
#ColumnResult(name="order_title", type = String.class)
}
)
}
)
And I created a new POJO that is not an entity named WorkOrderDTO.
#PersistenceContext
private EntityManager em;
#Override
public Collection<WorkOrderDTO> getWork() {
Query query = em.createNativeQuery(
"SELECT Sub1.wo_number, Sub2.service_types, Sub1.order_title FROM (SELECT * FROM workorder) Sub1 INNER JOIN (SELECT wo_number, GROUP_CONCAT(service_type SEPARATOR ', ') AS 'service_types' FROM service_type GROUP BY wo_number) Sub2 ON Sub1.wo_number=Sub2.wo_number WHERE fleet_company_id=4 AND (order_status='On-Bidding' OR order_status='Draft')", "workorder");
#SuppressWarnings("unchecked")
Collection<WorkOrderDTO> dto = query.getResultList();
Iterable<WorkOrderDTO> itr = dto;
return (Collection<WorkOrderDTO>)itr;
}
At last, the users who hated me for posting the same problem won't be annoyed anymore.

Categories