I'm using Hibernate + HSQL on JBOSS server, I need to saveOrUpdate() an Object which has an ID represented by another class:
public class RideId implements java.io.Serializable {
private int beginPop;
private int endPop;
private String requestUser;
public RideId() {
}
public RideId(int beginPop, int endPop, String requestUser) {
this.beginPop = beginPop;
this.endPop = endPop;
this.requestUser = requestUser;
}
...
so, "RideID" is the ID of the entity "Ride"
public class Ride implements java.io.Serializable {
private RideId id;
private User userByRequestUser;
private User userByAcceptUser;
private Pop pop;
private Boolean rideStatus;
public Ride() {
}
public Ride(RideId id, User userByRequestUser, Pop pop) {
this.id = id;
this.userByRequestUser = userByRequestUser;
this.pop = pop;
}
public Ride(RideId id, User userByRequestUser, User userByAcceptUser,
Pop pop, Boolean rideStatus) {
this.id = id;
this.userByRequestUser = userByRequestUser;
this.userByAcceptUser = userByAcceptUser;
this.pop = pop;
this.rideStatus = rideStatus;
}
...
how can I saveOrUpdate() a new Object of type Ride?
Thanks everyone and sorry for my english!
It's simple. You need to create first a new RideId, assign it to a new Ride and call saveOrUpdate with the Ride.
RideId id = new RideId(1, 2, "someuser");
Ride ride = new Ride(id, ...);
session.saveOrUpdate(ride);
Related
I am writing a PUT request API with spring and mongodb. But the save() inserts a new object instead of update the current one.
#Document("Test")
public class Expense {
#Field(name = "name")
private String expenseName;
#Field(name = "category")
private ExpenseCategory expenseCategory;
#Field(name = "amount")
private BigDecimal expenseAmount;
public Expense( String expenseName, ExpenseCategory expenseCategory, BigDecimal expenseAmount) {
this.expenseName = expenseName;
this.expenseCategory = expenseCategory;
this.expenseAmount = expenseAmount;
}
public String getExpenseName() {
return expenseName;
}
public void setExpenseName(String expenseName) {
this.expenseName = expenseName;
}
public ExpenseCategory getExpenseCategory() {
return expenseCategory;
}
public void setExpenseCategory(ExpenseCategory expenseCategory) {
this.expenseCategory = expenseCategory;
}
public BigDecimal getExpenseAmount() {
return expenseAmount;
}
public void setExpenseAmount(BigDecimal expenseAmount) {
this.expenseAmount = expenseAmount;
}
}
This is my reporsitory class
public interface ExpenseRepository extends MongoRepository<Expense, String> {
}
This is my Service class which shows how to update the class.
#Service
public class ExpenseService {
private final ExpenseRepository expenseRepository;
public ExpenseService(ExpenseRepository expenseRepository) {
this.expenseRepository = expenseRepository;
}
public void updateExpense(String id, Expense expense){
Expense savedExpense = expenseRepository.findById(id)
.orElseThrow(() -> new RuntimeException(
String.format("Cannot Find Expense by ID %s", id)));
savedExpense.setExpenseName(expense.getExpenseName());
savedExpense.setExpenseAmount(expense.getExpenseAmount());
savedExpense.setExpenseCategory(expense.getExpenseCategory());
expenseRepository.save(savedExpense);
}
}
This is my controller
#RestController
#RequestMapping("/api/expense")
public class ExpenseController {
private final ExpenseService expenseService;
public ExpenseController(ExpenseService expenseService) {
this.expenseService = expenseService;
}
#PutMapping("/{id}")
public ResponseEntity<Object> updateExpense(#PathVariable String id, #RequestBody Expense expense){
expenseService.updateExpense(id, expense);
return ResponseEntity.ok().build();
}
}
As shown in mongodb compass, mongodb auto generates an _id field for every object. So I do not define a id field or use #id annotation to define a primary for the collection. However, in the service class, expenseRepository.findById(id) retrieves the desired object and update it. Why does save() do the insert instead of update? Many thanks.
JPA Can't find the existing entry as no id field id set. You need to add an id field and set generation type to auto.
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
I am trying to override the #AdminPresentation of the following attribute defined in ProductImpl:
#Column(name = "DISPLAY_TEMPLATE")
#AdminPresentation(friendlyName = "ProductImpl_Product_Display_Template",
group = GroupName.Advanced)
protected String displayTemplate;
Currently, it is displayed as a text field by default as there is no fieldType attribute provided. But I want to display a dropdown select menu with predefined values such as Product and Plan. Here is what I've tried so far:
I've created a class DisplayTemplateType that implements BroadleafEnumerationType and defined PLAN and PRODUCT enums. Here is the code of that class:
public class DisplayTemplateType implements Serializable, BroadleafEnumerationType {
private static final long serialVersionUID = 7761108654549553693L;
private static final Map<String, DisplayTemplateType> TYPES = new LinkedHashMap<String, DisplayTemplateType>();
public static final DisplayTemplateType PLAN = new DisplayTemplateType("PLAN", "PLAN");
public static final DisplayTemplateType PRODUCT = new DisplayTemplateType("PRODUCT", "PRODUCT");
public static DisplayTemplateType getInstance(final String type) {
return TYPES.get(type);
}
private String type;
private String friendlyType;
public DisplayTemplateType() {
//do nothing
}
public DisplayTemplateType(final String type, final String friendlyType) {
this.friendlyType = friendlyType;
setType(type);
}
#Override
public String getType() {
return type;
}
#Override
public String getFriendlyType() {
return friendlyType;
}
private void setType(final String type) {
this.type = type;
if (!TYPES.containsKey(type)) {
TYPES.put(type, this);
} else {
throw new RuntimeException("Cannot add the type: (" + type + "). It already exists as a type via " + getInstance(type).getClass().getName());
}
}
// equals() and hashCode() implementation is removed for readability
}
Then in applicationContext-admin.xml file, I have added the following override properties:
<mo:override id="blMetadataOverrides">
<mo:overrideItem ceilingEntity="org.broadleafcommerce.core.catalog.domain.Product">
<mo:field name="displayTemplate">
<mo:property name="explicitFieldType" value="BROADLEAF_ENUMERATION"/>
<mo:property name="broadleafEnumeration" value="com.community.core.domain.DisplayTemplateType"/>
</mo:field>
</mo:overrideItem>
</mo:override>
But it didn't change anything. Am I missing something here?
Finally, after trying many things, I came up with a workaround. Instead of going with the XML based approach, I had to extend the ProductImpl class to override #AdminPresentation of its attributes. But for extending I needed to define an #Entity and as a result, I needed to create a useless table to bind to that entity. I know this is not the perfect approach but I couldn't find any better solution for this. Here is my code, so that someone might get help from it in the future:
#Entity
#Immutable
#AdminPresentationMergeOverrides({
#AdminPresentationMergeOverride(name = "displayTemplate", mergeEntries = {
#AdminPresentationMergeEntry(propertyType = PropertyType.AdminPresentation.FIELDTYPE, overrideValue = "BROADLEAF_ENUMERATION"),
#AdminPresentationMergeEntry(propertyType = PropertyType.AdminPresentation.BROADLEAFENUMERATION, overrideValue = "com.community.core.domain.DisplayTemplateType"),
#AdminPresentationMergeEntry(propertyType = PropertyType.AdminPresentation.REQUIREDOVERRIDE, overrideValue = "REQUIRED"),
#AdminPresentationMergeEntry(propertyType = PropertyType.AdminPresentation.DEFAULTVALUE, overrideValue = "PLAN")
})
})
public class CustomProduct extends ProductImpl {
private static final long serialVersionUID = -5745207984235258075L;
}
This is how it is displayed now:
I currently have 2 Arraylists which have Customer and Bike constructors data. I managed to enter both successfully to rent Arraylist using:
rent.add(new Rent(customers.get(1),bike.get(1)));
How do I check if CustomerID is already in Arraylist rent, and it will give error saying customer already renting?
public Rent(Customer customer, Bike bike) {
this.customers = customer;
this.bike = bike;
}
public Customer(int CustID, String CustFName, String CustLName) {
this.CustID = CustID;
this.CustFName = CustFName;
this.CustLName = CustLName;
}
public Bike(int BikeID, String BikeType, int PricePerDay,booleanisAvailable) {
this.BikeID = BikeID;
this.BikeType = BikeType;
this.PricePerDay = PricePerDay;
this.isAvailable = isAvailable;
}
protected ArrayList<Customer> customers = new ArrayList<Customer();
protected ArrayList<Bike> bike = new ArrayList<Bike>();
protected ArrayList<Rent> rent = new ArrayList<Rent>();
Assuming you are looking for a customer with a given custId, you can do this:
public boolean isAlreadyRenting(Customer cust) {
return rent.stream().anyMatch(r -> r.getCustomer().getCustId() == cust.getCustId());
}
If you override the equals method for your objects you can use contains on your ArrayList instances.
Want to do free text search in objecify and do distinct, my situation is like this:
1) NamedTrivialNew class:
public class NamedTrivialNew implements Serializable {
private String title;
private String city;
...
}
public class KeyWord implements Serializable {
#Id
public Long id;
#Parent
public Key<NamedTrivialNew> reason;
public KeyWord(){
}
3)
Search filter class:
NamedTrivialNew n = new NamedTrivialNew();
n.setSomeString("search test");
KeyWord hp = new KeyWord();
hp.reason = Key.create(NamedTrivialNew.class, 123L);
hp.id = 456L;
Key<KeyWord> hpKey = ofy().save().entity(hp).now();
ofy().clear();
assert ofy().load().key(hpKey).now() != null;
QueryResultIterator<KeyWord> NamedTrivialNew = ofy().load().type(KeyWord.class).filter("keyword>=", "search").filter("keyword <=", "search\uFFFD").iterator();
I am following this sample:
https://groups.google.com/forum/#!topic/objectify-appengine/Uc6_f98Tuao
Iterable reasons = ofy.query(Keyword.class).filter("keyword
=", "basic").filter("keyword <=", "basic\uFFFD").fetchParents();
There is no method: fetchParents();
i have tried above sample but it is not working....
Two entity classes:
#Entity
public class FilesInfo {
#Id
#GeneratedValue
private Integer id;
private String name;
private String url;
#OneToMany(cascade= CascadeType.ALL)
#JoinColumn(name="fileId")
private Collection<FilesShare> filesShared = new ArrayList<FilesShare>();
public Collection<FilesShare> getFilesShared() {
return filesShared;
}
public void setFilesShared(Collection<FilesShare> filesShared) {
this.filesShared = filesShared;
}
the second:
#Entity
public class FilesShare {
#Id
#GeneratedValue
private Integer id;
#Column(name="fileId")
private Integer fileId;
private int userId;
private int owner;
#ManyToOne
#JoinColumn(name="fileId", updatable=false,insertable=false)
private FilesInfo filesInfo;
public FilesInfo getFilesInfo() {
return filesInfo;
}
public void setFilesInfo(FilesInfo filesInfo) {
this.filesInfo = filesInfo;
}
the daoimpl mmethod:
public List<FilesInfo> reqSharedFiles(FilesShare fs) {
session=HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
List<FilesInfo> filesInfo = null;
filesInfo=(List<FilesInfo>)session.createQuery("from FilesInfo a, FilesShare b where a.id=b.fileId and b.userId=5 and b.owner=1").list();
now i dont understand when hibernate is mapping and returning the object by i am getting this error in action that it cant be casted :
Ljava.lang.Object; cannot be cast to app.domain.FilesInfo
The action
private List<FilesInfo> furls= new ArrayList<FilesInfo>();
furls=upload.reqSharedFiles(fs);
for(FilesInfo s: furls) // ERROR IS SHOWING HERE
{
System.out.println(s.getUrl());
}
Your query does not return a list of FilesInfo, but a list of two-element object arrays where the objects are of type FilesInfo and FilesShare.
You could either rewrite your query so that it only returns a FilesInfo, or attach a ResultTransformer that pulls out the part you're interested in or constructs an object that you can use to get the info you really want.
Your query can result in two diffrent objects, from FilesInfo a, FilesShare b so if it is a FileShare object it cannot be cast to a FilesInfo
see hql from
Thankyou all. Here is what i did after some search.
private List<Object[]> turls=new ArrayList<Object[]>(); //get the list of Object[] from HQL
for(Object[] r : turls)
{
FilesInfo inf =(FilesInfo)r[0];
System.out.println(inf.getUrl());
}