Hibernate Annotation-Mapping für Eltern/Kind-Beziehung?
Ich Probleme mit dem mapping ManyToOne von Eltern-Kind-Beziehung. Die OneToMany-Sammlung füllt sich faul in Ordnung. Allerdings, das inverse zu einem einzelnen Unternehmen, nicht.
Ich habe eine Tabelle von Server-Instanzen, die unveränderlich ist.
Wenn ich erstellen Sie eine Liste von Servern, füllt es die Sammlung von Anforderungen, die einem Server zugewiesen hat, um es ohne Probleme.
Wenn ich eine neue Anforderung, und wählen Sie die Server bevorzugt aus einer dropdown, saveOrUpdate (oder sogar versucht zu laden, und bekommen) es wird nicht aufgefüllt, die Server-Eigenschaft in der Anfrage-Instanz.
Server.java
public class Server {
private int serverId;
private List<Request> requests;
...
@OneToMany(mappedBy="server", fetch=FetchType.LAZY)
public List<Request> getRequests() {
return requests;
}
}
Request.java
public class Request {
private int requestId;
private int server_serverId; //foreign key to Server.serverId
private Server server;
...
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="server_serverId", nullable=false, updatable=false, insertable=false}
@ForeignKey(name="server_serverId", inverseName="serverId") //Don't think this really does anything
public Server getServer() {
return server;
}
}
hinzufügen.jsp (Add Request form)
...
<form:select id="preferred-server" path="server.serverId">
<c:forEach items="${servers}" var="server">
<form:option value="${server.serverId}">${server.serverName}</form:option>
</c:forEach>
</form:select>
...
AddRequestController.java
public class AddRequestController extends SimpleFormController {
...
@Override
protected ModelAndView onSubmit(Object command) throws Exception {
Request request = (Request)command;
try {
logger.info("BEFORE SAVE, request.server = " + request.getServer());
} catch (NullPointerException npe) {
logger.error("onSubmit() caught NPE: " + npe);
}
//Would rather not do these next two lines. Would prefer to saveOrUpdate
//Request, and have it populate server property via server_serverId foreign key.
//Server server = serverDao.loadByServerId(request.getServer_serverId());
//request.setServer(server);
//Added this instead, which calls getHibernateTemplate().refresh(server, LockMode.READ)
serverDao.refreshServer(request.getServer());
requestDao.addRequest(request); //calls getHibernateTemplate.saveOrUpdate(request)
try {
logger.info("AFTER SAVE, request.server = " + request.getServer());
} catch (NullPointerException npe) {
logger.error("onSubmit() caught NPE: " + npe);
}
return new ModelAndView(getSuccessView(), "request", request);
}
}
Habe ich versucht, praktisch jede Kombination von Annotation-mapping konnte ich online finden, und das ist das setup, das funktioniert mit dem abrufen einer Sammlung von Anfragen.
Nun, natürlich, ich kann meinen Wunsch Befehl Objekt aus der SimpleFormController, laden Sie das Server-Objekt basierend auf was der Benutzer wählt, und speichern Sie es auf diese Weise-aber das ist nicht der Punkt der Beziehung mapping, jetzt ist es?
Irgendwelche Vorschläge? Lassen Sie mich wissen, wenn Sie irgendwelche anderen code.
Mit: Spring 2.5, Hibernate 3.2.5, Sybase DB
Du musst angemeldet sein, um einen Kommentar abzugeben.
Das problem ist, dass
Request
ist die besitzenden Seite, so müssen Sie den server auf die Anfrage, also rufen SiesetServer()
. Dieserver
Bereich ist verantwortlich für die entsprechende Spalte in Ihrer Datenbank.Reicht es nicht aus, fügen Sie die Anfrage in die Liste, da ist das genau das inverse mapping. Wenn Sie möchten, legen Sie den server in der Anfrage und laden Sie dann den server aus der db, wird die Anfrage automatisch in die Liste aufgenommen (obwohl Sie normalerweise nicht tun, aber manuell fügen Sie den server in der Liste als gut).
Damit die Anfrage sollte so Aussehen:
server_serverId
in der Anfrage-Tabelle sowieso. Beachten Sie, dass Sie möchten vielleicht auch zu beschäftigen, lazy loading, ich werde aktualisieren, die Antwort entsprechend.serverId
Spalte und ordnen Sie die server-id. In diesem Fall würde dann tatsächlich fügen Sie dieupdatable=false, insertable=false
und am Ende haben zwei Felder einer Spalte. Beachten Sie, dass Sie sollten auch in der Lage sein, erstellen Sie eine getrennte server-Entität, die id setzen und rufensetServer()
. In diesem Fall sollten Sie darauf achten, nicht zu Kaskade alles auf server beim speichern der Anfrage. Ich würde schauen, dass die zweite Zufahrt, obwohl (oder Sie könnte es tun), also nicht auf das verlassen,.EntityManager.refresh()
auf die Entität. Andere als die, die Sie tatsächlich beginnen könnte, eine neue Frage, da diese Reihe von Kommentaren, die immer Recht lange und andere sind nicht so wahrscheinlich Folgen 😉refresh()
lädt aus der DB, aber wenn Sie wollen, um das Objekt aus dem cache sollten Sie versuchenEntityManager.findById()
die erste fragt den cache und sucht dann das Objekt aus der DB.