I want to map two object with mapStruct
public class EntityA
{
#Id
private String id;
#Column
private String anotherField
The second object with an object a paramter
public class ABC
{
private final ObjectXYZ identification;
// another fields
public class ObjectXYZ
{
private final String identification;
My Mapper:
#Mapper
public interface ObjectMapper
{
#Mapping(target = "identification", source = "identification", qualifiedByName = "ObjectXYZ")
ABC toABC(EntityA entity);
EntityA toEntityA(Material material);
#Named("ObjectXYZ")
#Mapping(target = "identification", source = "identification")
ObjectXYZ toObjectXYZ(String identification);
}
how can i map the EntityA.id to ABC.identification.identification
Objects definition:
public class EntityA {
private String id;
private String anotherField;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getAnotherField() {
return anotherField;
}
}
public class ABC {
private final ObjectXYZ identification;
private final String anotherField;
public ABC(ObjectXYZ identification, String anotherField) {
this.identification = identification;
this.anotherField = anotherField;
}
public String getAnotherField() {
return anotherField;
}
public ObjectXYZ getIdentification() {
return identification;
}
}
public class ObjectXYZ
{
private String identification;
public ObjectXYZ(String identification) {
this.identification = identification;
}
public String getIdentification() {
return identification;
}
}
Mapper:
Mapstruct automatically determines the methods or constructors for mapping, you need just specify the right target\source properties.
#Mapper
public interface ObjectMapper
{
#Mapping(target = "identification", source = "entity.id")
#Mapping(target = "anotherField", source = "entity.anotherField")
ABC toABC(EntityA entity);
#Mapping(target = "identification", source = "identification")
ObjectXYZ toObjectXYZ(String identification);
}
Generated code:
public class ObjectMapperImpl implements ObjectMapper {
#Override
public ABC toABC(EntityA entity) {
if ( entity == null ) {
return null;
}
ObjectXYZ identification = null;
String anotherField = null;
identification = toObjectXYZ( entity.getId() );
anotherField = entity.getAnotherField();
ABC aBC = new ABC( identification, anotherField );
return aBC;
}
#Override
public ObjectXYZ toObjectXYZ(String identification) {
if ( identification == null ) {
return null;
}
String identification1 = null;
identification1 = identification;
ObjectXYZ objectXYZ = new ObjectXYZ( identification1 );
return objectXYZ;
}
}
Related
I have two entities as below and the main problem is when I want to update the AccountRequestStatus entity. I save the integer enum code of AccountRequestStatusEnum in the database to persist the AcountRequest status in the whole application.
AccountRequestStatusEnum
public enum AccountRequestStatusEnum {
INITIAL(0),
SUCCESS(1);
private final Integer type;
AccountRequestStatusEnum(Integer type) {
this.type = type;
}
public Integer getType() {
return type;
}
public static AccountRequestStatusEnum of(Integer type) {
for (AccountRequestStatusEnum accountRequestStatusEnum : AccountRequestStatusEnum.values()) {
if (type.equals(accountRequestStatusEnum.getType()))
return accountRequestStatusEnum;
}
return null;
}
}
AccountRequest
#Entity
#Table(name = "T_ACCOUNT_REQUEST", uniqueConstraints = {#UniqueConstraint(columnNames = {"ACCOUNT_NO", "MESSAGE_ID"})})
#SequenceGenerator(
name = "SEQ_T_ACCOUNT_REQUEST",
sequenceName = "SEQ_T_ACCOUNT_REQUEST",
allocationSize = 1)
#AllArgsConstructor
#NoArgsConstructor
#EqualsAndHashCode(callSuper = false)
#ToString
public class AccountRequest extends AbstractAuditingEntity {
private Long id;
private String messageId;
private String issuer;
private EventType type;
private EventName name;
private String accountNo;
private LocalDateTime dateTime;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_T_ACCOUNT_REQUEST")
#Column(name = "ID", nullable = true, insertable = true, updatable = true, precision = 0)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Column(name = "MESSAGE_ID")
public String getMessageId() {
return messageId;
}
public void setMessageId(String messageId) {
this.messageId = messageId;
}
#Column(name = "ISSUER")
public String getIssuer() {
return issuer;
}
public void setIssuer(String issuer) {
this.issuer = issuer;
}
#Transient
public EventType getType() {
return type;
}
public void setType(EventType type) {
this.type = type;
}
#Column(name = "TYPE")
public Integer getEventTypeCode() {
if (Objects.nonNull(type)) {
return type.getType();
} else return null;
}
public void setEventTypeCode(Integer typeCode) {
type = EventType.of(typeCode);
}
#Transient
public EventName getName() {
return name;
}
public void setName(EventName name) {
this.name = name;
}
#Column(name = "NAME")
public Integer getEventNameCode() {
if (Objects.nonNull(name)) {
return name.getType();
} else return null;
}
public void setEventNameCode(Integer type) {
name = EventName.of(type);
}
#Column(name = "ACCOUNT_NO")
public String getAccountNo() {
return accountNo;
}
public void setAccountNo(String accountNo) {
this.accountNo = accountNo;
}
#Column(name = "DATE_TIME")
public LocalDateTime getDateTime() {
return dateTime;
}
public void setDateTime(LocalDateTime dateTime) {
this.dateTime = dateTime;
}
}
AccountRequestStatus
#Entity
#Table(name = "T_ACCOUNT_REQUEST_STATUS")
#SequenceGenerator(
name = "SEQ_T_ACCOUNT_REQUEST_STATUS",
sequenceName = "SEQ_T_ACCOUNT_REQUEST_STATUS",
allocationSize = 1
)
#AllArgsConstructor
#NoArgsConstructor
#ToString
public class AccountRequestStatus extends AbstractAuditingEntity {
private Long id;
private AccountRequestStatusEnum accountRequestStatusEnum;
private AccountRequest accountRequest;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_T_ACCOUNT_REQUEST_STATUS")
#Column(name = "ID", nullable = true, insertable = true, updatable = true, precision = 0)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Transient
public AccountRequestStatusEnum getAccountRequestStatusEnum() {
return accountRequestStatusEnum;
}
public void setAccountRequestStatusEnum(AccountRequestStatusEnum accountRequestStatusEnum) {
this.accountRequestStatusEnum = accountRequestStatusEnum;
}
#Column(name = "ACCOUNT_REQUEST_STATUS")
public Integer getAccountRequestStatusCode() {
if (Objects.nonNull(accountRequestStatusEnum)) {
return accountRequestStatusEnum.getType();
} else return null;
}
public void setAccountRequestStatusCode(Integer type) {
accountRequestStatusEnum = AccountRequestStatusEnum.of(type);
}
#ManyToOne(targetEntity = AccountRequest.class)
#JoinColumn(name = "ACCOUNT_REQUEST", referencedColumnName = "ID")
public AccountRequest getAccountRequest() {
return accountRequest;
}
public void setAccountRequest(AccountRequest accountRequest) {
this.accountRequest = accountRequest;
}
}
The first time that an account request comes from MQ my to application, I save the initial code of AccountRequestStatusEnum in service like below. This status persists properly and there is no problem, but when I want to update the AccountRequestStatus and add a new success code of AccountRequestStatusEnum (in another service) it won't be saved in DB.
This is the first service that is called after receiving the account request and saving the initial code.
#Service
#Transactional(readOnly = true)
public class AccountRequestServiceImpl implements IAccountRequestService {
#Value("${mq.event_argument_key}")
private String eventArgumentKey;
private final AccountRequestRepository accountRequestRepository;
private final AccountRequestStatusServiceImpl mqRequestStatusService;
private final EventToAccountRequestEntityMapper eventMapper;
private final AccountRequestMapper accountRequestMapper;
#Autowired
public AccountRequestServiceImpl(AccountRequestRepository accountRequestRepository,
AccountRequestStatusServiceImpl mqRequestStatusService,
EventToAccountRequestEntityMapper eventMapper,
AccountRequestMapper accountRequestMapper) {
this.accountRequestRepository = accountRequestRepository;
this.mqRequestStatusService = mqRequestStatusService;
this.eventMapper = eventMapper;
this.accountRequestMapper = accountRequestMapper;
}
#Override
#Transactional(propagation = Propagation.REQUIRES_NEW)// to prevent rollback for whole receive method in mq service
public void saveAccountRequest(Event event) {
AccountRequest accountRequest = eventMapper.eventToAccountRequest(event, eventArgumentKey);
accountRequestRepository.save(accountRequest);
AccountRequestDto accountRequestDto = accountRequestMapper.toDto(accountRequest);
saveAccountRequestStatus(accountRequestDto, AccountRequestStatusEnum.INITIAL);
}
private void saveAccountRequestStatus(AccountRequestDto accountRequestDto, AccountRequestStatusEnum status) {
AccountRequestStatusDto accountRequestStatusDto = new AccountRequestStatusDto();
accountRequestStatusDto.setAccountRequestStatusEnum(status);
accountRequestStatusDto.setAccountRequestDto(accountRequestDto);
mqRequestStatusService.saveAccountRequestStatus(accountRequestStatusDto);
}
}
This is the second service that should save the success code of AccountRequestStatus.
#Service
#Transactional(readOnly = true)
public class SyncLegacyAccountServiceImpl implements ISyncLegacyAccountService {
#Value("${mq.event_argument_key}")
private String eventArgumentKey;
#Value("${range.account_title_code}")
private String accountTitleCode;
private static final Logger log = LoggerFactory.getLogger(SyncLegacyAccountServiceImpl.class);
private final AccountMapRepository accountMapRepository;
private final AccountRequestRepository accountRequestRepository;
private final CustomerRepository customerRepository;
private final CustomerPersonRepository customerPersonRepository;
private final CustomerCompanyRepository customerCompanyRepository;
private final IMQService iMQService;
private final AccountRequestStatusServiceImpl accountRequestStatusServiceImpl;
private final GalaxyApi galaxyApi;
private final RangeApi rangeApi;
private final CustomerMapper customerMapper;
private final InquiryMapper inquiryMapper;
private final AccountRequestMapper accountRequestMapper;
private final EventToAccountRequestEntityMapper eventToAccountRequestMapper;
#Override
public void handleSyncRequest(Event event) {
saveSuccessfulAccountStatus(event); // ****** This is the main issue******
try {
CustomerAccountResponseDto galaxyData = getGalaxyData(event);
Optional<AccountMapEntity> optAccountMapEntity = accountMapRepository.findByNewAccountNo(event.getArgument().get(eventArgumentKey).toString());
if (!optAccountMapEntity.isPresent()) {
//openAccount(event);
} else {
AccountMapEntity accountMapEntity = optAccountMapEntity.get();
CustomerAccountResponseDto customerData = getCustomerData(accountMapEntity);
// save in legacy
}
} catch (Exception exception) {
handleEventRequestException(exception, event);
}
}
private void handleEventRequestException(Exception exception, Event event) {
if (exception instanceof RangeServiceException) {
log.error("Something went wrong with the Range service!");
throw new RangeServiceException();
} else if (exception instanceof GalaxySystemException) {
log.error("Something went wrong with the Galaxy service!");
NotifyAccountChangeResponse notifyAccountChangeResponse = MQUtil.buildAccountChangeResponse(new GalaxySystemException(), null, event.getMessageId());
iMQService.send(notifyAccountChangeResponse);
throw new GalaxySystemException();
}
}
public void saveSuccessfulAccountStatus(Event event) {
AccountRequest accountRequest = eventToAccountRequestMapper.eventToAccountRequest(event, eventArgumentKey);
AccountRequestDto accountRequestDto = accountRequestMapper.toDto(accountRequest);
saveAccountRequestStatus(accountRequestDto, AccountRequestStatusEnum.SUCCESS);
}
public void saveAccountRequestStatus(AccountRequestDto accountRequestDto, AccountRequestStatusEnum status) {
AccountRequestStatusDto accountRequestStatusDto = new AccountRequestStatusDto();
accountRequestStatusDto.setAccountRequestStatusEnum(status);
accountRequestStatusDto.setAccountRequestDto(accountRequestDto);
accountRequestStatusServiceImpl.saveAccountRequestStatus(accountRequestStatusDto);
}
}
AccountRequestStatusServiceImpl
#Service
#Transactional(readOnly = true)
public class AccountRequestStatusServiceImpl implements IAccountRequestStatusService {
private final AccountRequestStatusRepository accountRequestStatusRepository;
private final AccountRequestStatusMapper accountRequestStatusMapper;
#Autowired
public AccountRequestStatusServiceImpl(AccountRequestStatusRepository accountRequestStatusRepository,
AccountRequestStatusMapper accountRequestStatusMapper) {
this.accountRequestStatusRepository = accountRequestStatusRepository;
this.accountRequestStatusMapper = accountRequestStatusMapper;
}
#Override
#Transactional
public void saveAccountRequestStatus(AccountRequestStatusDto accountRequestStatusDto) {
AccountRequestStatus accountRequestStatus = accountRequestStatusMapper.toAccountRequestStatus(accountRequestStatusDto);
accountRequestStatusRepository.save(accountRequestStatus);
}
}
AccountRequestDto
#Data
public class AccountRequestDto {
private Long id;
private String messageId;
private String issuer;
private EventType type;
private EventName name;
private String accountNo;
private LocalDateTime dateTime;
}
AccountRequestStatusDto
#Data
public class AccountRequestStatusDto {
private Long id;
private AccountRequestStatusEnum accountRequestStatusEnum;
private AccountRequestDto accountRequestDto;
}
AccountRequestStatusMapper
#Mapper(componentModel = "spring")
public interface AccountRequestStatusMapper extends EntityToDtoMapper<AccountRequestStatusDto, AccountRequestStatus>, DtoToEntityMapper<AccountRequestStatusDto, AccountRequestStatus> {
#Mapping(target = "accountRequest.id", source = "accountRequestDto.id")
#Mapping(target = "accountRequest.messageId", source = "accountRequestDto.messageId")
#Mapping(target = "accountRequest.issuer", source = "accountRequestDto.issuer")
#Mapping(target = "accountRequest.type", source = "accountRequestDto.type")
#Mapping(target = "accountRequest.name", source = "accountRequestDto.name")
#Mapping(target = "accountRequest.accountNo", source = "accountRequestDto.accountNo")
#Mapping(target = "accountRequest.dateTime", source = "accountRequestDto.dateTime")
#Named(value = "toAccountRequestStatus")
AccountRequestStatus toAccountRequestStatus(AccountRequestStatusDto accountRequestStatusDto);
#Mapping(target = "accountRequestDto.id", source = "accountRequest.id")
#Mapping(target = "accountRequestDto.messageId", source = "accountRequest.messageId")
#Mapping(target = "accountRequestDto.issuer", source = "accountRequest.issuer")
#Mapping(target = "accountRequestDto.type", source = "accountRequest.type")
#Mapping(target = "accountRequestDto.name", source = "accountRequest.name")
#Mapping(target = "accountRequestDto.accountNo", source = "accountRequest.accountNo")
#Mapping(target = "accountRequestDto.dateTime", source = "accountRequest.dateTime")
#Named(value = "toAccountRequestStatusDto")
AccountRequestStatusDto toAccountRequestStatusDto(AccountRequestStatus accountRequestStatus);
}
Your #Transactional annotations at class level are marked as readonly = true. This prevents any database persistence, hence no saving.
However, in your first service you have #Transactional(propagation = Propagation.REQUIRES_NEW), which creates/propagates a net new transaction outside the scope of the readonly transaction. Thus your first service is able to persist to the database and your second is not.
I would suggest removing the readonly = true or potentially adding the propagation = Propagation.REQUIRES_NEW to the second service's transaction.
I fixed the issue by adding the saveSuccessfulAccountRequest to the AccountRequestServiceImpl service as below, and calling the saveSuccessfulAccountRequest in SyncLegacyAccountServiceImpl service. The main point of this approach is that saveSuccessfulAccountRequest should have propagation = Propagation.REQUIRES_NEW, without this, it does not work!!! But actually, I am not sure why it should be propagation = Propagation.REQUIRES_NEW :)))
#Service
#Transactional(readOnly = true)
public class AccountRequestServiceImpl implements IAccountRequestService {
#Value("${mq.event_argument_key}")
private String eventArgumentKey;
private final AccountRequestRepository accountRequestRepository;
private final AccountRequestStatusServiceImpl mqRequestStatusService;
private final EventToAccountRequestEntityMapper eventMapper;
private final AccountRequestMapper accountRequestMapper;
#Autowired
public AccountRequestServiceImpl(AccountRequestRepository accountRequestRepository,
AccountRequestStatusServiceImpl mqRequestStatusService,
EventToAccountRequestEntityMapper eventMapper,
AccountRequestMapper accountRequestMapper) {
this.accountRequestRepository = accountRequestRepository;
this.mqRequestStatusService = mqRequestStatusService;
this.eventMapper = eventMapper;
this.accountRequestMapper = accountRequestMapper;
}
#Override
#Transactional(propagation = Propagation.REQUIRES_NEW)// to prevent rollback for whole receive method in mq service
public void saveAccountRequest(Event event) {
AccountRequest accountRequest = eventMapper.eventToAccountRequest(event, eventArgumentKey);
accountRequestRepository.save(accountRequest);
AccountRequestDto accountRequestDto = accountRequestMapper.toDto(accountRequest);
saveAccountRequestStatus(accountRequestDto, AccountRequestStatusEnum.INITIAL);
}
#Override
#Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveSuccessfulAccountRequest(Event event) {
AccountRequest accountRequestByMessageId = accountRequestRepository.findByMessageId(event.getMessageId());
AccountRequestDto accountRequestDto = accountRequestMapper.toDto(accountRequestByMessageId);
saveAccountRequestStatus(accountRequestDto, AccountRequestStatusEnum.SUCCESS);
}
private void saveAccountRequestStatus(AccountRequestDto accountRequestDto, AccountRequestStatusEnum status) {
AccountRequestStatusDto accountRequestStatusDto = new AccountRequestStatusDto();
accountRequestStatusDto.setAccountRequestStatusEnum(status);
accountRequestStatusDto.setAccountRequestDto(accountRequestDto);
mqRequestStatusService.saveAccountRequestStatus(accountRequestStatusDto);
}
}
#Service
#Transactional(readOnly = true)
public class SyncLegacyAccountServiceImpl implements ISyncLegacyAccountService {
#Value("${mq.event_argument_key}")
private String eventArgumentKey;
#Value("${range.account_title_code}")
private String accountTitleCode;
private static final Logger log = LoggerFactory.getLogger(SyncLegacyAccountServiceImpl.class);
private final CustomerRepository customerRepository;
private final CustomerPersonRepository customerPersonRepository;
private final CustomerCompanyRepository customerCompanyRepository;
private final AccountMapRepository accountMapRepository;
private final IMQService iMQService;
private final IAccountRequestService iAccountRequestService;
private final GalaxyApi galaxyApi;
private final RangeApi rangeApi;
private final CustomerMapper customerMapper;
private final InquiryMapper inquiryMapper;
public SyncLegacyAccountServiceImpl(CustomerRepository customerRepository,
CustomerPersonRepository customerPersonRepository,
CustomerCompanyRepository customerCompanyRepository,
AccountMapRepository accountMapRepository,
#Lazy IMQService iMQService,
IAccountRequestService iAccountRequestService,
GalaxyApi galaxyApi,
RangeApi rangeApi,
CustomerMapper customerMapper,
InquiryMapper inquiryMapper) {
this.customerRepository = customerRepository;
this.customerPersonRepository = customerPersonRepository;
this.customerCompanyRepository = customerCompanyRepository;
this.accountMapRepository = accountMapRepository;
this.iMQService = iMQService;
this.iAccountRequestService = iAccountRequestService;
this.galaxyApi = galaxyApi;
this.rangeApi = rangeApi;
this.customerMapper = customerMapper;
this.inquiryMapper = inquiryMapper;
}
#Override
public void handleSyncRequest(Event event) {
saveSuccessfulAccountRequestStatus(event);
try {
CustomerAccountResponseDto galaxyData = getGalaxyData(event);
Optional<AccountMapEntity> optAccountMapEntity = accountMapRepository.findByNewAccountNo(event.getArgument().get(eventArgumentKey).toString());
if (optAccountMapEntity.isPresent()) {
//openAccount(event);
}
} catch (Exception exception) {
handleEventRequestException(exception, event);
}
}
}
I am trying to fetch list of train entities using source and destination properties of route entity which has one to many relationship with each other. The train table having route id as foreign key. The table names are route and train respectively. Please help me as the query is throwing java.lang.IllegalArgumentException: Validation failed for query for method public abstract java.util.List com.infyrail.app.repository.RouteRepository.findBySourceDestination(java.lang.String,java.lang.String)!
RouteRepository:
public interface RouteRepository extends JpaRepository<RouteEntity, Integer> {
#Query("SELECT t FROM train t JOIN route r WHERE r.source=?1 AND r.destination=?2")
public List<TrainEntity> findBySourceDestination(String source,String destination);
}
RouteEntity:
#Entity
#Table(name="route")
public class RouteEntity {
#Id
#GenericGenerator(name="route_id",
strategy="com.infyrail.app.generator.RouteIdGenerator")
#GeneratedValue(generator = "route_id")
#Min(value = 100)
#Max(value = 999)
Integer id;
String source;
String destination;
#OneToMany(mappedBy = "route",
cascade=CascadeType.ALL,orphanRemoval = true)
private List<TrainEntity> trainList;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public String getDestination() {
return destination;
}
public void setDestination(String destination) {
this.destination = destination;
}
public List<TrainEntity> getTrainList() {
return trainList;
}
public void setTrainList(List<TrainEntity> trainList) {
this.trainList = trainList;
}
}
TrainEntity:
#Entity
#Table(name="train")
public class TrainEntity {
//#GeneratedValue(strategy = GenerationType.IDENTITY)
#Id
#GenericGenerator(name="train_id",
strategy="com.infyrail.app.generator.TrainIdGenerator")
#GeneratedValue(generator = "train_id")
#Min(value = 100)
#Max(value = 999)
Integer id;
String trainName;
String arrivalTime;
String departureTime;
Double fare;
#ManyToOne(fetch = FetchType.LAZY)
#Autowired
RouteEntity route;
public RouteEntity getRoute() {
return route;
}
public void setRoute(RouteEntity route) {
this.route = route;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTrainName() {
return trainName;
}
public void setTrainName(String trainName) {
this.trainName = trainName;
}
public String getArrivalTime() {
return arrivalTime;
}
public void setArrivalTime(String arrivalTime) {
this.arrivalTime = arrivalTime;
}
public String getDepartureTime() {
return departureTime;
}
public void setDepartureTime(String departureTime) {
this.departureTime = departureTime;
}
public Double getFare() {
return fare;
}
public void setFare(Double fare) {
this.fare = fare;
}
}
Here is the problem. Your query should define the table bean name instead of the actual table name.
In your case you should use TrainEntity instead of train and RouteEntity instead of route.
public interface RouteRepository extends JpaRepository<RouteEntity, Integer> {
#Query("SELECT t FROM TrainEntity t JOIN RouteEntity r WHERE r.source=?1 AND r.destination=?2")
public List<TrainEntity> findBySourceDestination(String source,String destination);
}
Is it possible to fetch Data from 3 tables in hibernate where the controller is of a different model.
codeAModel.Java
#Entity
#Table(name="demo")
//#NamedQuery(name="Demo.findAll", query="SELECT m FROM Demo m")
public class AModel implements Serializable {
#Column(name="demo_loc")
private String location;
#Column(name="name")
private String name;
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
BModel.Java
#Entity
#Table(name="location")
//#NamedQuery(name="City.findAll", query="SELECT c FROM City c")
public class BModel implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="locationNoid")
private int locationNoId;
#Column(name="Code")
private int Code;
public int getLocationNoId() {
return locationNoId;
}
public void setLocationNoId(int locationNoId) {
this.locationNoId = locationNoId;
}
public int getCode() {
return Code;
}
public void setCode(int code) {
Code = code;
}
}
CModel.java
#Entity
#Table(name="offers")
public class CModel implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int OfferShopid;
#Column(name="offerCount")
private int offerCount;
#Column(name="foodCount")
private int foodCount;
public int getOfferShopid() {
return OfferShopid;
}
public void setOfferShopid(int offerShopid) {
OfferShopid = offerShopid;
}
public int getOfferCount() {
return offerCount;
}
public void setOfferCount(int offerCount) {
this.offerCount = offerCount;
}
public int getFoodCount() {
return foodCount;
}
public void setFoodCount(int foodCount) {
this.foodCount = foodCount;
}
}
DemoDTO.java
public class LocationDTO {
private int demoId;
private String name;
private int Code;
private int foodCount;
public int getDemoId() {
return demoId;
}
public void setDemoId(int demoId) {
this.demoId = demoId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getCode() {
return Code;
}
public void setCode(int code) {
Code = code;
}
public int getFoodCount() {
return foodCount;
}
public void setFoodCount(int foodCount) {
this.foodCount = foodCount;
}
}
DemoController.java
#RestController
#RequestMapping("/api/abcService")
#Api(description = "REST API to list details")
public class DemoController {
#Autowired
private DemoService DemoService;
#RequestMapping(value = "/list/v1/{user_id}/uid/{locationNoId}/location",
method = RequestMethod.GET)
#ResponseBody
#ApiOperation(value = "Get all Lists", notes = "Get all Address related
information")
public ResponseEntity<?> getAll(#PathVariable("user_id") int userId,
#PathVariable("locationNoId") int locationNoId)
{
try {
ModelMapper modelMapper = new ModelMapper();
Type listType = new TypeToken<List<DemoDTO>>() {
}.getType();
List<DemoDTO> listAll=DemoService.ListAll(userId,locationNoId);
return new ResponseEntity<>(listAll, HttpStatus.OK);
}catch (Exception ex){
String errorMessage;
errorMessage = ex.getMessage();
return new ResponseEntity<>(errorMessage, HttpStatus.BAD_REQUEST);
}
}
}
DemoDAOImpl
#Component
#Repository
#Transactional
public class DemoDAOImpl implements DemoDAO {
#PersistenceContext
private EntityManager entityManager;
#Autowired
private AService aService;
AModel aModel;
#Override
public #ResponseBody List<DemoDTO> ListAll(int User_id, int locationNoId) {
// TODO Auto-generated method stub
List<DemoDTO> listDemo=new ArrayList<>();
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<AModel> query =
criteriaBuilder.createQuery(AModel.class); Root<AModel> root =
query.from(AModel.class); query.select(root); CriteriaQuery<AModel>
select = query.select(root); TypedQuery<AModel> typedQuery =
entityManager.createQuery(select); List<AModel> AllLists =
typedQuery.getResultList();
for(AModel listofAll :AllLists ) {
System.out.println(listofAll.getid());
System.out.println(listofAll.getname());
System.out.println(listofAll.getlocation());
System.out.println(listofAll.getid());
System.out.println(listofAll.getRating());
listMalls.(AllLists);
return listMalls;
}
Base DemoController you have already a DemoService that you can reuse between other controlers. So if you have
#RestController
#RequestMapping("/api/abcServiceA")
public class DemoControllerA {
#Autowired
private DemoServiceA demoServiceA;
#RestController
#RequestMapping("/api/abcServiceB")
public class DemoControllerB {
#Autowired
private DemoServiceB demoServiceB;
You can create controler:
#RestController
#RequestMapping("/api/abcServiceB")
public class DemoControllerD {
#Autowired
private DemoServiceA demoServiceA;
#Autowired
private DemoServiceB demoServiceB;
Use this two services in one method:
#RequestMapping(value = "/list/v1/{user_id}/uid/{locationNoId}/location",method = RequestMethod.GET)
#ResponseBody
#ApiOperation(value = "Get all Lists", notes = "Get all Address related information")
public ResponseEntity<?>getAll(#PathVariable("user_id")int userId,
#PathVariable("locationNoId")int locationNoId) {
try {
ModelMapper modelMapper = new ModelMapper();
Type listType = new TypeToken<List<DemoDTO>>() {}.getType();
List<DemoDTO> listAllFromA = aemoServiceA.ListAll(userId, locationNoId);
List<DemoDTO> listAllFromB = aemoServiceB.ListAll(userId, locationNoId);
// do something with listAllFromA and listAllFromB
return new ResponseEntity<>(listAll, HttpStatus.OK);
} catch (Exception ex) {
String errorMessage;
errorMessage = ex.getMessage();
return new ResponseEntity<>(errorMessage, HttpStatus.BAD_REQUEST);
}
}
I have three tables which called SLSNotification,SLSWorkflow and Importer These tables are not any relationships... I want to get three tables for jasper report.. So I create a native query for it.. It works fine on MySQL... But when i add it to the SLSWorkflowRepository retrieve only workflow class only.. I want to get other classes also from this repository... I think it retrieves only because i write this like this
#Query(value = "select * from slsnotification a join sls_wrkflw b on a.snumber = b.snumber join importers c on c.importer_vat_number = a.importervat where a.importervat = :importerVatNumber and a.snumber = :snumber", nativeQuery = true)
Object getForPrint(#Param("snumber") Long snumber,#Param("importerVatNumber") String importerVatNumber);
can i get other classes for SLSIWorkflow getForPrint() methord...
If i wrong please give some onother way...
This is my models
SLSNotification Model
#Entity
#Table(name = "slsnotification")
public class SLSNotification {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(length = 16)
private Long snumber;
#Column(length = 100)
private String serialCord;
private String date;
// #JsonFormat(pattern = "yyyy-MM-dd")
// private Date appPostdate = new Date();
#Column(nullable = false)
private String appPostdate;
#Column(length = 8)
private String cusOffice;
#Column(length = 1)
private String cusSerial;
#Column(length = 50)
private String cusDecNo;
#JsonFormat(pattern = "yyyy-MM-dd")
private Date cusDate;
#Column(length = 300)
private String manufacturer;
#Column(length = 300)
private String exporterAddress;
#Column(length = 20, nullable = false)
private String importerVAT;
#NotEmpty
#Column(length = 20, nullable = false)
private String declarantVAT;
private String declarantDetails;
private String vessel;
private String blNo;
private String loadingPort;
private String tradingCountry;
private String countryOrigin;
private String invoiceNo;
#JsonFormat(pattern = "yyyy-MM-dd")
private Date invoiceDate;
private Double invoiceValue;
public Long getSnumber() {
return snumber;
}
public void setSnumber(Long snumber) {
this.snumber = snumber;
}
public String getSerialCord() {
return serialCord;
}
public void setSerialCord(String serialCord) {
this.serialCord = serialCord;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getCusOffice() {
return cusOffice;
}
public void setCusOffice(String cusOffice) {
this.cusOffice = cusOffice;
}
public String getCusSerial() {
return cusSerial;
}
public void setCusSerial(String cusSerial) {
this.cusSerial = cusSerial;
}
public String getCusDecNo() {
return cusDecNo;
}
public void setCusDecNo(String cusDecNo) {
this.cusDecNo = cusDecNo;
}
public Date getCusDate() {
return cusDate;
}
public void setCusDate(Date cusDate) {
this.cusDate = cusDate;
}
public String getManufacturer() {
return manufacturer;
}
public void setManufacturer(String manufacturer) {
this.manufacturer = manufacturer;
}
public String getExporterAddress() {
return exporterAddress;
}
public void setExporterAddress(String exporterAddress) {
this.exporterAddress = exporterAddress;
}
public String getImporterVAT() {
return importerVAT;
}
public void setImporterVAT(String importerVAT) {
this.importerVAT = importerVAT;
}
public String getDeclarantVAT() {
return declarantVAT;
}
public void setDeclarantVAT(String declarantVAT) {
this.declarantVAT = declarantVAT;
}
public String getVessel() {
return vessel;
}
public void setVessel(String vessel) {
this.vessel = vessel;
}
public String getBlNo() {
return blNo;
}
public void setBlNo(String blNo) {
this.blNo = blNo;
}
public String getLoadingPort() {
return loadingPort;
}
public void setLoadingPort(String loadingPort) {
this.loadingPort = loadingPort;
}
public String getTradingCountry() {
return tradingCountry;
}
public void setTradingCountry(String tradingCountry) {
this.tradingCountry = tradingCountry;
}
public String getCountryOrigin() {
return countryOrigin;
}
public void setCountryOrigin(String countryOrigin) {
this.countryOrigin = countryOrigin;
}
public String getInvoiceNo() {
return invoiceNo;
}
public void setInvoiceNo(String invoiceNo) {
this.invoiceNo = invoiceNo;
}
public Date getInvoiceDate() {
return invoiceDate;
}
public void setInvoiceDate(Date invoiceDate) {
this.invoiceDate = invoiceDate;
}
public Double getInvoiceValue() {
return invoiceValue;
}
public void setInvoiceValue(Double invoiceValue) {
this.invoiceValue = invoiceValue;
}
SLSWorkflow Model
#Entity
#Table(name = "sls_wrkflw")
public class SLSIWorkflow {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long SNumber;
private String qc;
private String inv;
private String manuTr;
private String packList;
private String blAttached;
private String otherDoc;
private String otherDocName;
private String ad;
private String MAUsername;
private String appMan;
private String accptdQc;
private String accptTR;
private String manufacturer;
private String validMark;
private String otherDocBoolean;
private String cnfrmtyTest;
private String dtSampling;
private String otherDocDet;
private String adUsername;
private String recom;
private String reaRec;
private String tests;
private String wfStatus;
public Long getSNumber() {
return SNumber;
}
public void setSNumber(Long SNumber) {
this.SNumber = SNumber;
}
public String getQc() {
return qc;
}
public void setQc(String qc) {
this.qc = qc;
}
public String getInv() {
return inv;
}
public void setInv(String inv) {
this.inv = inv;
}
public String getManuTr() {
return manuTr;
}
public void setManuTr(String manuTr) {
this.manuTr = manuTr;
}
public String getPackList() {
return packList;
}
public void setPackList(String packList) {
this.packList = packList;
}
public String getBlAttached() {
return blAttached;
}
public void setBlAttached(String blAttached) {
this.blAttached = blAttached;
}
public String getMaattachUser() {
return maattachUser;
}
public void setMaattachUser(String maattachUser) {
this.maattachUser = maattachUser;
}
public String getMauser() {
return mauser;
}
public void setMauser(String mauser) {
this.mauser = mauser;
}
public String getMareattachUser() {
return mareattachUser;
}
public void setMareattachUser(String mareattachUser) {
this.mareattachUser = mareattachUser;
}
public String getOtherDoc() {
return otherDoc;
}
public void setOtherDoc(String otherDoc) {
this.otherDoc = otherDoc;
}
public String getOtherDocName() {
return otherDocName;
}
public void setOtherDocName(String otherDocName) {
this.otherDocName = otherDocName;
}
}
Importer Model
#Entity
#Table(name = "importers")
public class Importer {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "importer_id")
private long importerId;
private String importerBrc;
#NotEmpty
#Column(unique = true, nullable = false)
private String importerVatNumber;
#Column(nullable = false)
private String category;
private String importerSVatNumber;
#NotEmpty
private String importerName;
private String importerAddress1;
#NotEmpty
private String officePhoneNumber;
#NotEmpty
private String mobilePhoneNumber;
#Email
#NotEmpty
private String email;
#Email
private String optemail1;
#Email
private String optemail2;
#NotEmpty
private String userIDandTime;
#NotEmpty
private String recentUpdateBy;
public String getOptemail1() {
return optemail1;
}
public void setOptemail1(String optemail1) {
this.optemail1 = optemail1;
}
public String getOptemail2() {
return optemail2;
}
public void setOptemail2(String optemail2) {
this.optemail2 = optemail2;
}
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinTable(name = "importer_agents",
joinColumns = {
#JoinColumn(name = "importerId")},
inverseJoinColumns = {
#JoinColumn(name = "agentId")})
private List<Agent> agentList;
public String getImporterBrc() {
return importerBrc;
}
public void setImporterBrc(String importerBrc) {
this.importerBrc = importerBrc;
}
public String getImporterVatNumber() {
return importerVatNumber;
}
public void setImporterVatNumber(String importerVatNumber) {
this.importerVatNumber = importerVatNumber;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public String getImporterSVatNumber() {
return importerSVatNumber;
}
public void setImporterSVatNumber(String importerSVatNumber) {
this.importerSVatNumber = importerSVatNumber;
}
public String getImporterName() {
return importerName;
}
public void setImporterName(String importerName) {
this.importerName = importerName;
}
public String getImporterAddress1() {
return importerAddress1;
}
public void setImporterAddress1(String importerAddress1) {
this.importerAddress1 = importerAddress1;
}
}
SLSIWorkflowRepository
public interface SLSIWorkflowRepository extends CrudRepository<SLSIWorkflow,Long> {
#Override
SLSIWorkflow save(SLSIWorkflow slsiWorkflow);
#Override
SLSIWorkflow findOne(Long Long);
#Override
boolean exists(Long Long);
#Override
Iterable<SLSIWorkflow> findAll();
#Override
long count();
#Override
void delete(SLSIWorkflow entity);
#Query(value = "select * from slsnotification a join sls_wrkflw b on a.snumber = b.snumber join importers c on c.importer_vat_number = a.importervat where a.importervat = :importerVatNumber and a.snumber = :snumber", nativeQuery = true)
Object getForPrint(#Param("snumber") Long snumber,#Param("importerVatNumber") String importerVatNumber);
WorkflowServices
public class WorkflowServices {
private static final Logger serviceLogger = LogManager.getLogger(WorkflowServices.class);
private static final String INIT_WORKFLOW_STATUS = "INIT";
#Autowired
private SLSIWorkflowRepository workflowRepository;
#Autowired
private FileSystemStorageService storageService;
#Autowired
private SLSNotificationRepository slsNotificationRepository;
public void initWorkflow(Long slsNumber) {
SLSIWorkflow workflow = new SLSIWorkflow();
workflow.setSNumber(slsNumber);
workflow.setWfStatus(INIT_WORKFLOW_STATUS);
workflowRepository.save(workflow);
}
public SLSIWorkflow getApplicationForPrint(Long SNumber, String importerVatNumber) {
return workflowRepository.getForPrint(SNumber, importerVatNumber);
}
}
Workflow Controller //this is large and i gives my cord only
#RequestMapping(path = "/viewTAXInvoice/{snumber}/{importerVatNumber}", method = RequestMethod.POST)
public ModelAndView getPDFReport(#PathVariable("snumber") String snumber, #PathVariable("importerVatNumber") String importerVatNumber) {
File reportsDir = Paths.get(servletContext.getRealPath(reportDataLocation)).toFile();
if (!reportsDir.exists()) {
throw ProductWithSameSerialExistsException.getInstance();
}
JRDataSource dataSource = new JRBeanCollectionDataSource(Arrays.asList(workflowServices.getApplicationForPrint(Long.parseLong(snumber), importerVatNumber)));
Map<String, Object> parameterMap = new HashMap<>();
parameterMap.put("datasource", dataSource);
parameterMap.put("JasperCustomSubReportDatasource", dataSource);
parameterMap.put(JRParameter.REPORT_FILE_RESOLVER, new SimpleFileResolver(reportsDir));
System.out.println("Dt Source1 "+dataSource);
return new ModelAndView("pdfReportforVAT", parameterMap);
}
How to connect three tables... Please help me someone...
You are getting a SLSIWorkflow only because you are returning that Entity only in the following code in WorkflowServices.
public SLSIWorkflow getApplicationForPrint(Long SNumber, String importerVatNumber) {
return workflowRepository.getForPrint(SNumber, importerVatNumber);
}
If you return an Object it will have all the fields from tables slsnotification, sls_wrkflw, importers as a Object[].
Plus using a Plain JOIN it will result in an INNER JOIN by default. This will not return anything if one joined table doesn't satisfy the ON criteria. It is good if you use LEFT JOIN so that the null will be returned.
These are my model classes:
Film.java
#Entity
public class Film {
private Integer id;
private String title;
private List<FilmActor> filmActors;
#OneToMany(mappedBy = "film")
public List<FilmActor> getFilmActors() {
return filmActors;
}
public void setFilmActors(List<FilmActor> filmActors) {
this.filmActors = filmActors;
}
}
Actor.java
#Entity
public class Actor {
private Integer id;
private String firstname;
private String lastname;
private List<FilmActor> filmActors;
#OneToMany(mappedBy = "actor")
public List<FilmActor> getFilmActors() {
return filmActors;
}
public void setFilmActors(List<FilmActor> filmActors) {
this.filmActors = filmActors;
}
}
And this is the Join Table Entity:
#Entity
#Table(name = "film_actor")
public class FilmActor {
private FilmActorPK id;
private Film film;
private Actor actor;
private Timestamp lastUpdate;
#EmbeddedId
public FilmActorPK getId() {
return id;
}
public void setId(FilmActorPK id) {
this.id = id;
}
#ManyToOne
#MapsId("film")
#JoinColumn(name = "film_id")
public Film getFilm() {
return film;
}
public void setFilm(Film film) {
this.film = film;
}
#ManyToOne
#MapsId("actor")
#JoinColumn(name = "actor_id")
public Actor getActor() {
return actor;
}
public void setActor(Actor actor) {
this.actor = actor;
}
#Column(name = "last_update")
public Timestamp getLastUpdate() {
return lastUpdate;
}
public void setLastUpdate(Timestamp lastUpdate) {
this.lastUpdate = lastUpdate;
}
}
and the Primary Key class:
#Embeddable
public class FilmActorPK implements Serializable {
private int actorId;
private int filmId;
#Column(name = "actor_id")
public int getActorId() {
return actorId;
}
public void setActorId(int actorId) {
this.actorId = actorId;
}
#Column(name = "film_id")
public int getFilmId() {
return filmId;
}
public void setFilmId(int filmId) {
this.filmId = filmId;
}
}
So I want to find films where 2 given actors acts. This is what I have:
#Override
public Collection<Film> filmsActorsTogether(Actor a, Actor b) {
final List<Film> filmsOfActorA = filmsOfActor(a);
final List<Film> filmsOfActorB = filmsOfActor(b);
final Collection<Film> intersection = CollectionUtils.intersection(filmsOfActorA, filmsOfActorB);
return intersection;
}
#Override
public List<Film> filmsOfActor(Actor actor) {
final EntityManager entityManager = persistenceUtil.getEntityManager();
final Actor persistentActor = entityManager.find(Actor.class, actor.getId());
final ArrayList<Film> films = new ArrayList<Film>();
for (FilmActor filmActor : persistentActor.getFilmActors()) {
films.add(filmActor.getFilm());
}
entityManager.close();
return films;
}
Is there any way to achieve this without fetching ALL films of 2 actors, and using filtering in memory? How do I get the Films directly from the DB with JQL?
Maybe there is something more elegant, but the following query should work:
select f from Film f where
(select count(fa.id) from FilmActor fa
where fa.film = f
and (fa.actor = :actor1 or fa.actor = :actor2)) = 2
Side note: your PK class should have a correct equals() and hashCode() methods