First of all sorry for my dump english but i would ask a little help..
I have two oracle Db tables (events,documents) and i made two entity classes.
one:
public class BDocuments implements Serializable {
#JoinColumn(name = "B_EVENT_ID", referencedColumnName = "ID")
#ManyToOne
private BEvents bEventId;
...
...
two:
public class BEvents implements Serializable {
#Id
#Basic(optional = false)
#GeneratedValue(generator="EventSeq")
#SequenceGenerator(name="EventSeq",sequenceName="B_EVENTS_SEQ", allocationSize=1)
#Column(name = "ID")
private Integer id;
...
...
the id field of event table is the foreign key for the documents table event_id field..
Whene the user create a new event on the view the program create a new instance to the events table and if the events has an attached document then i’ll create a instance to the documents table. And of course the new event instance’s id will be the new document instance’s event_id..
it workd fine.. there is no probleme if i check the tables with TOAD i can see the 2 new instance..
After this i’ll see the new event ont he view and if I’ll click on this int he new dialog window i should see the events details.. like does this event has any attached documents..
JSF:
<p:column>
<f:facet name="header">
<h:outputText value="Esemény ID"/>
</f:facet>
<h:commandLink value="#{item.id}" >
<p:ajax listener="#{mainWorkingBean.showChosedEventDetails('dlgshowevent',item.id)}" />
</h:commandLink>
</p:column>
<p:column>
There is a managed beans that has a metod showChosedEventDetails() and after some validation check it invoke the DAO EJB’s following method, and then create a data table for the view by the returned List.
This is EJB method:
public List<BDocuments> showAllDocumentsOnEvents(Integer chosedEventid) {
if (chosedEventid != null) {
try {
System.out.println("showAllDocumentsOnEvents: event id:" + chosedEventid);
assert emf != null;
EntityManager em = null;
em = emf.createEntityManager();
List<BDocuments> documentList = new ArrayList();
BEvents documentDetailsInstance = (BEvents) em.createNamedQuery("BEvents.findById").setParameter("id", chosedEventid).getSingleResult();
//get the event instance by the id that received in the method paramter…
System.out.println("showAllDocumentsOnEvents NEW CHOSED INSTANCE: " + documentDetailsInstance);
Collection<BDocuments> allDocumentsCollection = documentDetailsInstance.getBDocumentsCollection(); //a #ManytoOne..
System.out.println("showAllDocumentsOnEvents EVENTINSTANCE: " + documentDetailsInstance.getEventText());
System.out.println("showAllDocumentsOnEvents COLLECTION: " + allDocumentsCollection.toString());
System.out.println("showAllDocumentsOnEvents NEW COLLECTION SIZE..: " + allDocumentsCollection.size() + "collection: " + allDocumentsCollection.toString()); // lame debugging.. checking the values..
int x;
for (x = 0; x < allDocumentsCollection.size();) {
System.out.println("Show all: for ciklus: Iterables kiszedve: " + Iterables.get(allDocumentsCollection, x));
BDocuments document = Iterables.get(allDocumentsCollection, x);
documentList.add(document);
x++;
} //check the collection and put the elements to the list.. .
return documentList;
} catch (NullPointerException e) {
System.out.println(e.getMessage());
return null;
}
} else {
System.out.println(" showAllDocumentsOnEvents ELSE ÁG...showAllDocumentsOnEvents: event id:" + chosedEventid);
return null;
}
}
It is ALSO work fine BUT the Collection allDocumentsCollection is empty!
I couldn’t be empty because i can see in the database there is in everything what should be in.
And now comming the real big question.. after i make clean and build and redeploy in netbeans and then click ont he same event on the view the Collection allDocumentsCollection WILL NOT BE empty…
I’m really don’t know why is this Collection empty before the redeploy.. and why not after the redeploy..
I would be really thankfull if somebody could help me..
thank you!
Odd that you showed everything but the getBDocumentsCollection mapping that is causing you problems, or the code used to set the relationships. But since you are saying the database is populated correctly and this is a bidirectional relationship, it is a fairly common mistake to only populate one side of the relationship. When you set the BDocuments.bEventId with a BEvents instance, you must also add that BDocuments instance to the BEvents.BDocumentsCollection to keep the relationship in synch with the database. JPA does not maintain relationships for you, so you either set both sides, or constantly refresh the object from the database when the transaction commits using em.refresh or provider specific api. Since refreshing has additional overhead, it is much better to just always keep both sides in sync.
Related
Logic: Display drop down (data from TABLE_ONE) in page1.amx and based on the selection it needs to get data from TABLE_TWO, then render the retrieved data into page2.amx. Below is the sample which I have tried,
I have created service class ServiceClass.java in my service package and created DataControl (ServiceClassDC) for that class.
From my FirstPage.amx I'm calling service class method using valueChangeListener in drop down (Drop down value will be populated from DB, let's take TABLE_ONE ID). Below is the piece of code for this logic,
FirstPage.amx
<amx:selectOneChoice value="#{bindings.selectId.inputValue}" label="Select Id" id="soc1"
valueChangeListener="#{ServiceClass.callThisMethod}">
<amx:selectItems value="#{bindings.selectId.items}" id="si1"/>
</amx:selectOneChoice>
Based on the selection using WHERE condition, I got the list of objects in productList which is having the result set data.
ServiceClass.java
public void callThisMethod(ValueChangeEvent valueChangeEvent) {
System.out.println("Selected Value: "+valueChangeEvent.getNewValue());
String selectedValue = valueChangeEvent.getNewValue().toString();
ClassMappingDescriptor descriptor = ClassMappingDescriptor.getInstance(TableTwo.class);
DBPersistenceManager pm = getLocalPersistenceManager();
try{
StringBuffer sql = pm.getSqlSelectFromPart(descriptor);
sql.append(" WHERE ID='"+selectedValue+"'");
sql = pm.constructOrderByClause(sql, descriptor);
ResultSet set = pm.executeSqlSelect(sql.toString(), new ArrayList());
System.out.println("Result set >> "+set);
List productList = pm.createEntitiesFromResultSet(set, (List) descriptor.getAttributeMappingsDirect());
System.out.println("productList "+productList);
} catch(Exception exp){
System.out.println("Exception : "+exp);
}
}
Now, I want to display the List object data (productList) into SecondPage.amx screen. How to do this?
Please comment below, if you want any more details regarding this.
You need to expose your List productList in a public method (so provide a get method) and expose that method in a Data Control. You can then drag and drop it on your page.
Example:
public Product[] getProductArray() {
return (Product[]) productList.toArray();
}
Note that this is an example from a MAF version where Java 1.4 was used!
I have the following ManyToMany association within my Project:
Class User:
#ManyToMany(cascade=CascadeType.ALL)
#JoinTable(
joinColumns={#JoinColumn(name="user_id")},
inverseJoinColumns={#JoinColumn(name="antrag_id")}
)
private List<Antrag> antraege;
And Class Antrag:
#ManyToMany(mappedBy="antraege",cascade=CascadeType.ALL)
private List<User> users;
I am trying to correctly insert a new record, this - I think works not correctly. When I'm trying to "reselect" all Antraege of User, I am getting a NullPointerException on antraege.getUsers(). Only when I restart the java swing application, antraege.getUsers() doesn't return null.
Code for Inserting my new ManyToMany record:
Antrag antrag = new Antrag();
antrag.setBetreff(betreff);
antragBusiness.create(antrag);
betreuer.getAntraege().add(antrag);
currentUser.getAntraege().add(antrag);
userBusiness.update(betreuer);
userBusiness.update(currentUser);
Where my create method uses persist and the update method uses merge.
As I've said, they get inserted correctly into the database, but when I try to call:
List<Antrag> antraege = (List<Antrag>) user.getAntraege();
for(Antrag a : antraege){
News n = new News();
n.setDatum(a.getCreatedAt());
n.setStatus(a.isStatus());
n.setThema(a.getInfo());
List<User> beteiligte = a.getUsers();
System.out.println("Amount users " + beteiligte.size());
for (User z : beteiligte) {
System.out.println(z.getNachname() + " " + z.getId());
if(z.getId() != user.getId()){
n.setZustaendiger(z);
}
}
newsList.add(n);
}
-> Amount users returns 0 :(
So - in consequences: Antraege are added to Users, but users not to Antraege?
Edit: As it seems, my insertion of a new ManyToMany record is not correct.
Can anyone explain me the correct way ?
I am trying to learn how to work with hibernate, and until now i thought i was doing ok...
The problem is, i have a one to many relationship that i can't update/delete.
My DB is pretty basic, i have a ClientsBasic that has a one to many relationship with IndirectClients (which simply has a ClientsBasic ID and a URL, both keys because you can have for the same ID lots of URLs)
ClientBasic:
#OneToMany(fetch = FetchType.EAGER, mappedBy = "clientsBasic", cascade=CascadeType.ALL)
public List<IndirectClients> getIndirectClients() {
return this.indirectClients;
}
public void setIndirectClients(List<IndirectClients> indirectClients) {
// this.indirectClients = indirectClients;
this.indirectClients.clear();
this.indirectClients.addAll(indirectClients);
}
ClientDao:
public ClientsBasic save(ClientsBasic client) throws HibernateException {
Transaction tx = null;
tx = session.beginTransaction();
session.saveOrUpdate(client);
tx.commit();
log.info("Client saved with id: " + client.getClientId());
return client;
}
Now if i try to delete ClientsBasic, it will delete both ClientsBasic and all related indirectClients, so its working as expected, but if i simply try to update/delete and entry in indirectClients it doesn't work.
Example:
I create a new Client
ClientsBasic cb = new ClientsBasic("company_1", 1234, "company_1#email.com");
cbDao.save(cb);
And then a new Indirect Client
List<IndirectClients> indirectClientsSet= new ArrayList<IndirectClients>();
indirectClientsSet.add(new IndirectClients(new IndirectClientsId(cb.getClientId(), "www.url.test_1.com"), cb));
cb.setIndirectClients(indirectClientsSet);
cbDao.save(cb);
Now if i try to change the url like this
ClientsBasic cb = cbDao.findClientById(1);
List<IndirectClients> indC = cb.getIndirectClients();
indC.get(0).getId().setUrl("TEST");
cb.setIndirectClients(indC);
cbDao.save(cb);
no changes are made in the DB.
Can someone please help me?
Thank you.
If your IndirectClients is defined as an Entity it has its own life cycle, meaning you have to persist/delete instances separately from their ClientBasic parent.
If you want a scenario where all children are managed through their parent relation, consider using ElementCollection.
See also JPA: When to choose Multivalued Association vs. Element Collection Mapping
I would like to use p:rating component, to vote and save the value into the database (if it is already voted to be able to extract the value from the db later). In the Entity i have also comments fields and i would like if comments are already written to add only the vote so i sometimes i make merge instead of persist (if there is nothing for this request written in the DB).
I have the following code in my .xhtml page:
<h:form
rendered="#{not empty userRequestBean.request.hiredAgency.city}">
<p:rating value="#{userRequestBean.rating}" stars="10"
onRate="#{userRequestBean.rateAgency()}">
</p:rating>
</h:form>
In my bean I have:
#ManagedBean(name = "userRequestBean")
#SessionScoped
public class UserRequestBean implements Serializable {
private Integer rating; // Plus get and set methods
private TComment agencyComment = new TComment();
public void rateAgency() {
if (rating == null) return;
EntityManager em = HibernateUtil.getEntityManager();
if (!em.getTransaction().isActive())
em.getTransaction().begin();
Query queryAgencyComment = em.createQuery("select comment "
+ "from TRequest req join req.requestComments comment "
+ "where req.id = :requestId ");
Long requestId = (Long) request.getId();
queryAgencyComment.setParameter("requestId", requestId);
agencyComment = (TComment) queryAgencyComment.getSingleResult();
if (agencyComment.equals(null)) {
agencyComment = new TComment();
agencyComment.settRequest(request);
agencyComment.setCommentDate(new Date());
agencyComment.setAssessment(rating);
em.persist(agencyComment);
em.getTransaction().commit();
} else {
agencyComment.setAssessment(5);
em.merge(agencyComment);
em.getTransaction().commit();
}
}
But onRate, the method rateAgency is not executed. It is executed only once when the page is rendered. How can i implement this working?
The attribute onRate defines a JavaScript (client side) action, whilst you are trying to run a server method.
You need an ajax action instead:
<p:rating value="#{userRequestBean.rating}" stars="10" >
<p:ajax event="rate" listener="#{userRequestBean.rateAgency()}" />
</p:rating>
Useful links:
PrimeFaces showcase
A good JSF Tutorial (like Oracle's Java EE 7 Tutorial)
How do I get JPA to respect the Namespace I am setting when it generates keys?
I am using the following code to get the current user and set the Namespace to their UserId:
final OAuthService oauth = OAuthServiceFactory.getOAuthService();
final User user = oauth.getCurrentUser();
NamespaceManager.set(user.getUserId());
When I do the following I get the correctly information in my logs:
System.out.println("user.getUserId() = " + user.getUserId());
System.out.println("user.toString() = " + user.toString());
Here is how I am creating my Key inside the constructor of my Entity:
#Entity
public class ImageHandle
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#JsonSerialize(using = com.vertigrated.gae.cms.jackson.KeySerializer.class)
#JsonDeserialize(using = com.vertigrated.gae.cms.jackson.KeyDeserializer.class)
private Key key;
....
First thing I do in the constructor is :
this.key = KeyFactory.createKey(ImageHandle.class.getSimpleName(), uuid.toString());
The Google App Engine documentation says that the KeyFactory should use whatever the current NamespaceManager.get() returns, but it doesn't.
When I do the following code and I get the Namespace set to "" as output, even though I have set it to the user.getUserId() in the code above:
final ImageHandle ir = new ImageHandle(fs.getBlobKey(aef), uuid, url, name, w, h, s);
ENTITY_MANAGER.persist(ir);
System.out.println("ir.getKey().getNamespace() = " + ir.getKey().getNamespace());
Results in the output : ir.getKey().getNamespace() =
No Namespaces show up in the DataStore Viewer in the administration console either.
Does the JPA EntityManager in Google App Engine respect the current Namespace settings?
Solution
I figured out what the problem was, I am calling another method that is setting the Namespace in a finally block to my default Namespace, once I moved the NamespaceManager.set(user.getUserId()); below that method call, it fixed it.
Lesson Learned
I should be getting the current Namespace, storing it and and setting it back like the examples.