Java - How to let longblob by displayed on html page - java

So, my entire project seems to work for now. It is a simple system that holds records of all products of a shop. When a new product is made, a barcode will be generated. Now, this works, but I wanted to see my barcode(I can see the longblob in my db) in the output to be sure. I am probably doing it wrong, but I cannot get the image displayed.
The controller and html pages are quit irrelevant for now cause I just made them to see if I would see the barcode, but I don't. So what html tags do I need to use to get this barcode image displayed? I got the barcode object from here:
<dependency>
<groupId>net.sourceforge.barbecue</groupId>
<artifactId>barbecue</artifactId>
<version>1.5-beta1</version>
</dependency>
I will display the code from the html, controller and the object. You can find the entire project on git. https://github.com/Muschke/scruplesAntwerpenTwee.
html:
<html lang="nl" xmlns:th="http://www.thymeleaf.org">
<head th:replace="fragments::head(title='Index', css=#{/css/css.css})"></head>
<th:block th:if="${producten}">
<table>
<thead>
<th>Gebruiker</th>
<th>Consignatiebon</th>
<th>Eigenschap</th>
<th>Kleur</th>
<th>Merk</th>
<th>Maat</th>
<th>Soort</th>
<th>Barcode</th>
<th>Beschrijving</th>
<th>aankoopprijs</th>
<th>verkoopprijs</th>
<th>status</th>
<th>gestolen</th>
<th>solden</th>
</thead>
<tbody>
<tr th:each="product:${producten}" th:object="${product}">
<td th:text="*{getGebruiker().getNaam()}"></td>
<td th:text="*{getConsignatiebon().getidConsignatiebon()}"></td>
<td th:text="*{getEigenschap().getSubEigenschap()}"></td>
<td th:text="*{getKleur().getKleur()}"></td>
<td th:text="*{getMerk().getNaam()}"></td>
<td th:text="*{getMaat().getNaam()}"></td>
<td th:text="*{getSoort()}"></td>
<td>
<img class='img-thumbnail' th:src="'data:image/jpeg;base64,' + ${imgUtil.getImgData(product.getBarcode())}" />
</td>
<td th:text="*{getBeschrijving()}"></td>
<td th:text="*{getAankoopprijs()}"></td>
<td th:text="*{getVerkoopprijs()}"></td>
<td th:text="*{getStatus()}"></td>
<td th:text="*{getGestolen()}"></td>
<td th:text="*{getSolden()}"></td>
</tr>
</tbody>
</table>
<form th:action="#{/verwerken}" method="post">
<button name="barcodebutton">Genereer barcode</button>
</form>
</th:block>
</html>
controller:
#Controller
#RequestMapping("/")
class IndexController {
private final ProductService productService;
public IndexController(ProductService productService) {
this.productService = productService;
}
#GetMapping
public ModelAndView findAllProducts() {
return new ModelAndView("index").addObject("producten", productService.findAllProducts());
}
#PostMapping("/verwerken")
public ModelAndView barcodeToevoegen() {
var idnu = 52L;
productService.genereerBarcode(idnu);
return new ModelAndView("redirect:/");
}
}
object:
#Table(name = "producten")
public class Product {
#Id #GeneratedValue(strategy = GenerationType.IDENTITY)
private long productId;
#ManyToOne(fetch = FetchType.LAZY, optional = false) #JoinColumn(name = "gebruikerId")
private Gebruiker gebruiker;
#ManyToOne(fetch = FetchType.LAZY, optional = false) #JoinColumn(name = "consignatiebonId")
private Consignatiebon consignatiebon;
#OneToOne #JoinColumn(name = "eigenschapId")
private Eigenschap eigenschap;
#OneToOne #JoinColumn(name = "kleurId")
private Kleur kleur;
#OneToOne #JoinColumn(name = "merkId")
private Merk merk;
#OneToOne #JoinColumn(name = "maatId")
private Maat maat;
#Enumerated(EnumType.STRING)
private Soort soort;
private Barcode barcode;
/*de barcode mag null zijn bij input?, na input van alles, invoke methode creeër barcode.
* dat MOET dan na create worden uitgevoerd in transactional*/
private String beschrijving;
private BigDecimal aankoopprijs;
#Enumerated(EnumType.STRING)
private Status status;
private boolean gestolen;
private boolean solden;
public Product(Gebruiker gebruiker, Consignatiebon consignatiebon, Eigenschap eigenschap, Kleur kleur, Merk merk, Maat maat, Soort soort, Barcode barcode,
String beschrijving, BigDecimal aankoopprijs, Status status,boolean gestolen, boolean solden) {
this.gebruiker = gebruiker;
this.consignatiebon = consignatiebon;
this.eigenschap = eigenschap;
this.kleur = kleur;
this.merk = merk;
this.maat = maat;
this.soort = soort;
this.barcode = barcode;
this.beschrijving = beschrijving;
this.aankoopprijs = aankoopprijs;
this.status = status;
this.gestolen = gestolen;
this.solden = solden;
}
protected Product() {};
public Consignatiebon getConsignatiebon() {
return consignatiebon;
}
public Gebruiker getGebruiker() {
return gebruiker;
}
public long getProductId() {
return productId;
}
public Eigenschap getEigenschap() {
return eigenschap;
}
public Kleur getKleur() {
return kleur;
}
public Merk getMerk() {
return merk;
}
public Maat getMaat() {
return maat;
}
public Soort getSoort() {
return soort;
}
public Barcode getBarcode() {
return barcode;
}
public String getBeschrijving() {
return beschrijving;
}
public BigDecimal getAankoopprijs() {
return aankoopprijs;
}
public BigDecimal getVerkoopprijs() {
return aankoopprijs.multiply(BigDecimal.valueOf(2.5));
}
public Status getStatus() {
return status;
}
public boolean getGestolen() {
return gestolen;
}
public boolean getSolden() {
return solden;
}
/*setters voor vkp en gestolen, en voor elke OTO*/
public void setEigenschap(Eigenschap eigenschap) {
this.eigenschap = eigenschap;
}
public void setKleur(Kleur kleur) {
this.kleur = kleur;
}
public void setMerk(Merk merk) {
this.merk = merk;
}
public void setMaat(Maat maat) {
this.maat = maat;
}
public void setGestolen(boolean gestolen) {
this.gestolen = gestolen;
}
/*equals en hashtagcode maken*/
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Product)) return false;
Product product = (Product) o;
return Objects.equals(eigenschap, product.eigenschap) && Objects.equals(kleur, product.kleur) && Objects.equals(merk, product.merk) && Objects.equals(maat, product.maat) && soort == product.soort && Objects.equals(beschrijving, product.beschrijving) && Objects.equals(aankoopprijs, product.aankoopprijs);
}
#Override
public int hashCode() {
return Objects.hash(eigenschap, kleur, merk, maat, soort, beschrijving, aankoopprijs);
}
/*methode om barcode te genereren als er nog geen barcode is:
* we steken het id erin, laten aanvullen met nullen tot aan 12 getallen, 13e wordt automatisch gemaakt*/
//eventueel via #þostload automatisch laten invullen
public void generateAndSetEAN13BarcodeImage() throws Exception {
if(barcode != null) {
throw new IllegalArgumentException();
} else {
var lengte = String.valueOf(getProductId()).length();
StringBuilder langeId = new StringBuilder(String.valueOf(productId));
if (lengte < 12) {
var verschil = 12 - lengte;
for (int i = 0; i < verschil; i++) {
langeId.append(0);
}
}
barcode = BarcodeFactory.createEAN13(String.valueOf(langeId));
}
}
}
So, question again: how can I make the barcode be displayed on the html page?

Related

How to display records from a table with relationship mapping in Spring boot, CrudRepository and Thymeleaf

I am developing a simple CRUD project with Spring Boot. I have successfully accomplished connecting to the database and displaying records from ONE table. Now I want to show the "Phones" belonging to a "Client" but when I click on "VerDetalle" (http://localhost:8080/listar) it shows the table without any record (obviously the table has data)
I think the problem its with the method telefonosById(nro_cliente) of TelefonoService and verDetalle(#PathVariable Integer nro_cliente, Model model) of Controller.
"E01_cliente" and "E01_telefono" they are entities.
#Entity
public class E01_telefono {
private Integer codigo_area;
#Id
private Integer nro_telefono;
private char tipo;
private Integer nro_cliente;
#ManyToOne
private E01_cliente cliente;
//**Constructor and Getters and Setters**//
Entity E01_cliente:
#Entity
public class E01_cliente {
#Id
private Integer nro_cliente;
private String nombre;
private String apellido;
private String direccion;
private boolean activo;
#OneToMany(mappedBy = "cliente")
private Set<E01_telefono> telefonos;
}
Service Telefono:
#Service
public class TelefonoService implements IServiceTelefono {
#Autowired
private ITelefono telData;
#Override
public List<E01_telefono> AllPhones() {
return (List<E01_telefono>) telData.findAll();
}
#Override
public Optional<E01_telefono> telefonosById(Integer nro_cliente) {
return telData.findById(nro_cliente);
}
Controller:
#Controller
public class Controlador {
#Autowired
private IServiceCliente serviceCliente;
#Autowired
private IServiceTelefono serviceTelefono;
#GetMapping("/listar")
public String listarClientes(Model model){
List<E01_cliente> clientes = serviceCliente.listarClientes();
model.addAttribute("clientes", clientes);
return "index";
}
#GetMapping("/agregarCliente")
public String agregarCliente(Model model){
model.addAttribute("cliente", new E01_cliente());
//Cuando el usuario presione se mostrara el formulario correspondiente al Cliente
return "formulario";
}
#PostMapping("/guardarCliente")
public String guardarCliente(Model model, #Valid E01_cliente cliente){
serviceCliente.guardarCliente(cliente);
return "redirect:/listar";
}
#GetMapping("/editarCliente/{nro_cliente}")
public String editarCliente(#PathVariable Integer nro_cliente, Model model ){
Optional<E01_cliente> clientEdit = serviceCliente.listarId(nro_cliente);
model.addAttribute("cliente", clientEdit);
return "formulario";
}
#GetMapping("/eliminarCliente/{nro_cliente}")
public String borrarCliente(Model model, #PathVariable Integer nro_cliente){
serviceCliente.eliminarCliente(nro_cliente);
return "redirect:/listar";
}
#GetMapping("/verDetalle/{nro_cliente}")
public String verDetalle(#PathVariable Integer nro_cliente, Model model){
Optional<E01_telefono> telefonosCliente = serviceTelefono.telefonosById(nro_cliente);
if(telefonosCliente.isPresent()) {
model.addAttribute("telefonos", telefonosCliente);
}
return "detalleCliente";
}
}
HTML Thymeleaf "detalleCliente.html":
<body>
<div class="container mt-4">
<table class="table">
<thead>
<tr>
<th>Código Área</th>
<th>Teléfono</th>
<th>Tipo</th>
<th>Número Cliente</th>
</tr>
</thead>
<tbody>
<tr th:each="telefono:${telefonos}">
<td th:text="${telefono.codigo_area}"></td>
<td th:text="${telefono.nro_telefono}"></td>
<td th:text="${telefono.tipo}"></td>
<td th:text="${telefono.nro_cliente}"></td>
</tr>
</tbody>
</table>
</div>
</body>
If you want to put E01_cliente cliente from telefonosCliente to ${telefonos} try change
model.addAttribute("telefonos", telefonosCliente);
To
model.addAttribute("telefonos", telefonosCliente.get().getClientes());

Displaying Correct information on my webpage.

My question is How can I use my getLabel, getX, getY from my NodeEntity class and display the results of my query on my web page instead of getting "org.neo4j.ogm.response.model". I do not know if these get methods should be used within the controller or repository class in order to display the node information on the web page table.
#NodeEntity
public class Room {
#Id #GeneratedValue
private Long id;
#Property(name = "label")
private String label;
#Property(name = "shape")
private String shape;
#Property(name = "colour")
private String colour;
#Property(name = "x")
private String x;
#Property(name = "y")
private String y;
#Relationship(type = "To")
private Collection<Room> roomTo = new ArrayList<>();
#Relationship(type = "Up")
private Collection<Room> roomUp = new ArrayList<>();
#Relationship(type = "Down")
private Collection<Room> roomDown = new ArrayList<>();
#JsonIgnoreProperties("room")
#Relationship(type = "To", direction = Relationship.INCOMING)
Collection<RelEnt> relEnts;
public Room(){
}
public String getLabel(){
return label;
}
public String getShape(){
return shape;
}
public String getColour(){
return colour;
}
public String getX() {
return x;
}
public String getY() {
return y;
}
}
Repository:
public interface NavigatorRepository extends Neo4jRepository<Room, String>{
#Query("match (r1: Room {label: {from}}), (r2: Room {label: {to}}), p = shortestPath((r1)-[*]-(r2)) unwind nodes(p) as room return room")
Iterable<Map<String, Object>> getShortestRoute(#Param("from") String from, #Param("to") String to);
}
Service:
#Service
public class NavigatorService {
#Autowired
NavigatorRepository navigatorRepository;
public Iterable<Map<String, Object>> shortestRoute(String from, String to){
return navigatorRepository.getShortestRoute(from, to);
}
}
Controller:
#Controller
public class AunController {
#RequestMapping(value = "/AUN") //this will allow you to access web page with just http://localhost:8081/
public String homePage(){
return "AUN-Web"; //uses the static html file created for the web page
}
#Autowired
NavigatorService navigatorService;
#GetMapping(value = "/navigate")
public String navigate(#RequestParam(name="from") String from, #RequestParam(name="to") String to, Model model) {
Iterable<Map<String, Object>> route = navigatorService.shortestRoute(from, to);
model.addAttribute("from", from)
.addAttribute("route", route)
.addAttribute("to", to);
return "AUN-Results";
}
#GetMapping(value = "/")
public String error(){
return "Error/404";
}
}
HTML:
<form action="/navigate" method="">
<strong><label for="ifrom">Current Location:</label></strong> <br>
<input id="ifrom" type="text" placeholder="MB" name="from"><br>
<strong><label for="ito">Destination:</label></strong> <br>
<input id="ito" type="text" placeholder="MB" name="to"><br>
<p style="line-height: 30px; width: 300px;"></p>
<button type="button" class="btn btn-success" onclick="result">Search</button>
<p style="line-height: 30px; width: 300px;"></p>
</form>
</div>
<div align="center" class="container-fluid">
<h5>Going from <span th:text="${from}">MB220</span> to <span th:text="${to}">MB265</span></h5>
<table class="table">
<tr>
<th>Label</th>
<th>X</th>
<th>Y</th>
</tr>
<tr th:each="route : ${route}">
<td th:text="${route}">Mb220</td>
</tr>
</table>
</div>
Try to change your foreach var name to something like "routpoint" so it differs to the complete route.

Not able to Insert Data with Foreign Keys struts2

I have 3 entities (Medecin , Patient , Rendezvous)
Medecin with Idmed , Patient with Idpat are foreign key with ManyToOne relationship in Rendezvous.
When I add a Medecin or a Patient via a form , the Data is perfectly stored .
But when I try to add a Rendezvous , using a Form with two , struts2 select tag , <:select../> who are populated with the list of Id of Patient and Medecin .
Nothing happen.
I have a return success , but the Data is not stored .
How to fix that ?
My form, Rendezvous.jsp
<div class="col-md-4">
<div class="form_main">
<h4 class="heading"><strong>Planifier un </strong> Rendezvous <span></span></h4>
<div class="form">
<s:form action="Ajoutrdv" id="Ajoutrdv" namepace="/pages" theme="bootstrap" cssClass="bs-example form-horizontal">
<s:textfield label="Id du Rendezvous" type="Number" min="1" required="" placeholder="Entrer l'ID du RDV" name="idrdv"/>
<s:select label="Id du Patient" headerKey="-1" headerValue="" list="%{Patient}" listKey="idpat" name="idpat" required="" onchange="getData(this.value)"/>
<s:select label="Id du Medecin" headerKey="-1" headerValue="" list="%{Medecin}" listKey="idmed" name="idmed" required="" onchange="getData(this.value)"/>
<s:textfield type="Date" required="" name="date"></s:textfield>
<s:textfield type="Time" required="" name="heure"></s:textfield>
<s:textarea label="Motif" required="" name="motif"></s:textarea>
<caption><s:submit cssClass="btn btn-primary" value="Enregistrer"/></caption>
</s:form>
</div>
My action in struts2.xml
<package name="Ajoutrdv" namespace="/pages" extends="struts-default">
<action name="Ajoutrdv" class="controller.FormRDVAction" method="Ajoutrdv">
<result name="success">/pages/accueil.jsp</result>
<result name="input">/pages/Rendezvous.jsp</result>
</action>
</package>
FormRDVAction
public class FormRDVAction extends ActionSupport {
private Integer idrdv;
private Medecin idmed;
private Patient idpat;
private String date;
private String heure;
private String motif;
private List<Rendezvous> Rendezvous;
// getters setters
// Add action
public String Ajoutrdv() {
RendezvousDAO rdvDAO= RendezvousDAO.getInstance();
Rendezvous R = new Rendezvous();
R.setIdmed(idmed);
R.setIdpat(idpat);
R.setIdrdv(idrdv);
R.setDate(date);
R.setHeure(heure);
R.setMotif(motif);
rdvDAO.saveRendezvous(R);
return SUCCESS;
}
}
RendezvousDAO
public void saveRendezvous(Rendezvous Rendezvous) {
log.info("********** Debut saveRendezvous RendezvousDAO **********");
Session session = SessionFactoryUtil.getInstance().openSession();
Transaction trans = session.beginTransaction();
try {
session.save(Rendezvous);
if (!trans.wasCommitted()) {
trans.commit();
}
} catch (Exception e) {
e.printStackTrace();
log.fatal(e.getMessage());
trans.rollback();
} finally {
session.close();
}
}
Finally , mapping class Rendezvous.java
#Entity
#Table(name = "rendezvous")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Rendezvous.findAll", query = "SELECT r FROM Rendezvous r"),
#NamedQuery(name = "Rendezvous.findByIdrdv", query = "SELECT r FROM Rendezvous r WHERE r.idrdv = :idrdv"),
#NamedQuery(name = "Rendezvous.findByDate", query = "SELECT r FROM Rendezvous r WHERE r.date = :date"),
#NamedQuery(name = "Rendezvous.findByHeure", query = "SELECT r FROM Rendezvous r WHERE r.heure = :heure"),
#NamedQuery(name = "Rendezvous.findByMotif", query = "SELECT r FROM Rendezvous r WHERE r.motif = :motif")})
public class Rendezvous implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#Column(name = "idrdv")
private Integer idrdv;
#Basic(optional = false)
#Column(name = "date")
private String date;
#Basic(optional = false)
#Column(name = "heure")
private String heure;
#Basic(optional = false)
#Column(name = "motif")
private String motif;
#JoinColumn(name = "idpat", referencedColumnName = "idpat")
#ManyToOne(optional = false , fetch = FetchType.LAZY)
private Patient idpat;
#JoinColumn(name = "idmed", referencedColumnName = "idmed")
#ManyToOne(optional = false , fetch = FetchType.LAZY)
private Medecin idmed;
public Rendezvous() {
}
public Rendezvous(Integer idrdv) {
this.idrdv = idrdv;
}
public Rendezvous(Integer idrdv, String date, String heure, String motif) {
this.idrdv = idrdv;
this.date = date;
this.heure = heure;
this.motif = motif;
}
public Integer getIdrdv() {
return idrdv;
}
public void setIdrdv(Integer idrdv) {
this.idrdv = idrdv;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getHeure() {
return heure;
}
public void setHeure(String heure) {
this.heure = heure;
}
public String getMotif() {
return motif;
}
public void setMotif(String motif) {
this.motif = motif;
}
public Patient getIdpat() {
return idpat;
}
public void setIdpat(Patient idpat) {
this.idpat = idpat;
}
public Medecin getIdmed() {
return idmed;
}
public void setIdmed(Medecin idmed) {
this.idmed = idmed;
}
#Override
public int hashCode() {
int hash = 0;
hash += (idrdv != null ? idrdv.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Rendezvous)) {
return false;
}
Rendezvous other = (Rendezvous) object;
if ((this.idrdv == null && other.idrdv != null) || (this.idrdv != null && !this.idrdv.equals(other.idrdv))) {
return false;
}
return true;
}
#Override
public String toString() {
return "mapping.Rendezvous[ idrdv=" + idrdv + " ]";
}
}

how to databind list selected checkbox in spring mvc

Hi I am new to Spring Mvc i have 3 tables first is role,resources,roleresource tables respectively. I have a created a jsp in which a list of resources are shown along with check boxes and also rolename where user enters,my prob is i need to insert rolename to role table and generated roleid to roleresource table with selected resources ids. problem here is i am not able to bind selected checkbox values here is my controller
package com.steadyground.controller;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.steadyground.constants.URLConstants;
import com.steadyground.entity.Organization;
import com.steadyground.entity.Resources;
import com.steadyground.form.RoleResourceForm;
import com.steadyground.service.ResourcesService;
#Controller
public class RoleResoucesMappingController {
#Autowired
private ResourcesService resourcesService;
#RequestMapping(value = URLConstants.ROLERESOURCEMAPPING_PAGE, method = RequestMethod.GET)
public String landRoleResourceMapping(ModelMap map)
{
map.addAttribute("roleResourceForm",new RoleResourceForm());
return "roleResourcesMapping";
}
#RequestMapping(value = URLConstants.ROLERESOURCEMAPPING_ADD, method = RequestMethod.POST)
public String createRoleResourceMapping(#ModelAttribute(value="roleResourceForm") RoleResourceForm roleResourceForm, BindingResult result, ModelMap map)
{
System.out.println(roleResourceForm.getResources());
System.out.println(roleResourceForm.getResources().size());
//System.out.println(roleResourceForm.getRole().getRoleResources());
return "roleResourcesMapping";
}
#ModelAttribute("resources")
public List<Resources> getAllResources() {
List<Resources> listResources = new ArrayList<Resources>();
listResources = resourcesService.getAllResources();
return listResources;
}
}
here is my role.java file
#Entity
#Table(name = "role", catalog = "steadyground")
public class Role implements java.io.Serializable {
private Integer roleId;
private String roleName;
private Set<RoleResource> roleResources = new HashSet<RoleResource>(0);
public Role() {
}
public Role(String roleName) {
this.roleName = roleName;
}
public Role(String roleName, String applicationName,
Set<RoleResource> roleResources) {
this.roleName = roleName;
this.roleResources = roleResources;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "role_id", unique = true, nullable = false)
public Integer getRoleId() {
return this.roleId;
}
public void setRoleId(Integer roleId) {
this.roleId = roleId;
}
#Column(name = "role_name", nullable = false, length = 100)
public String getRoleName() {
return this.roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "role")
public Set<RoleResource> getRoleResources() {
return this.roleResources;
}
public void setRoleResources(Set<RoleResource> roleResources) {
this.roleResources = roleResources;
}
}
here is my resources.java
#Entity
#Table(name = "resources", catalog = "steadyground")
public class Resources implements java.io.Serializable {
private Integer resourceId;
private String url;
private String urlName;
public Resources() {
}
public Resources(String url, String urlName) {
this.url = url;
this.urlName = urlName;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "resource_id", unique = true, nullable = false)
public Integer getResourceId() {
return this.resourceId;
}
public void setResourceId(Integer resourceId) {
this.resourceId = resourceId;
}
#Column(name = "url", length = 100)
public String getUrl() {
return this.url;
}
public void setUrl(String url) {
this.url = url;
}
#Column(name = "url_name", length = 200)
public String getUrlName() {
return this.urlName;
}
public void setUrlName(String urlName) {
this.urlName = urlName;
}
}
here is my roleresource.java
#Entity
#Table(name="role_resource"
,catalog="steadyground"
)
public class RoleResource implements java.io.Serializable {
private Integer roleResourceId;
private Role role;
private Integer resourceId;
public RoleResource() {
}
public RoleResource(Role role, Integer resourceId) {
this.role = role;
this.resourceId = resourceId;
}
#Id #GeneratedValue(strategy=IDENTITY)
#Column(name="role_resource_id", unique=true, nullable=false)
public Integer getRoleResourceId() {
return this.roleResourceId;
}
public void setRoleResourceId(Integer roleResourceId) {
this.roleResourceId = roleResourceId;
}
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="role_id")
public Role getRole() {
return this.role;
}
public void setRole(Role role) {
this.role = role;
}
#Column(name="resource_id")
public Integer getResourceId() {
return this.resourceId;
}
public void setResourceId(Integer resourceId) {
this.resourceId = resourceId;
}
}
and my jsp page
<springform:form method="post" action="createRoleResourcesMapping" class="form-horizontal" commandName="roleResourceForm" >
<div class="span12">
<div class="center">
<div class="control-group span6">
<label class="control-label" for="Role_Id">Role Id</label>
<div class="control-group span6">
<label class="control-label" for="url_Name">Role Name</label>
<div class="controls">
<div class="span12">
<springform:input path="role.roleName"/>
</div>
</div>
</div>
<div class="page-header position-relative"></div>
<table id="sample-table-2" class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th>Resources</th>
</tr>
</thead>
<tbody>
<tr>
<td><springform:checkboxes path="resources" items="${resources}" itemLabel="urlName" itemValue="resourceId"/>
</td></tr></tbody>
</table>
<div class="controls">
<div class="span12">
<input type="submit" class="btn btn-primary" value="Submit">
<input type="button" class="btn " value="Cancel">
</div>
</div>
</div>
</div>
</springform:form>
could someone help me in how to receive the data and save it in two tables
<springform:checkboxes path="resources" items="${resources}" itemLabel="urlName" itemValue="resourceId"/>
From your code, what I've understood, the RoleResourcesForm is more like a wrapper of the 2 entities Resource & Role with another object resources.
I think, to use form:checkboxes you better give it an object List in the path.
And what's this variable resources?
If it's really an List object in the RoleResourcesForm wrapper, in the items, you should use
items="${roleResourceForm.resources}"
When you commit it, it will send the form model attribute with only checked checkbox values.

LazyInitialization Exception with Spring and Hibernate

I think i'm missing something fundamental about how Hibernate works, specifically with lazy loading. My problem is debugging, as I'm not sure if this is a Hibernate problem or a Spring problem in disguise. I thought I would ask here before doing some major refactoring.
I have two Entities. One holds a collection of the other in a OneToMany relationship. For my web page I wish to grab all of the first entity, and subsequently grab the set of associated entities for each and display them.
I believe my problem is this: I use a JpaTemplate to find all entities. This works fine, however because of Lazy loading I do not get the associated set of related entities. In my view (jsp) I want access to this set, but of course it is null because it is being lazy loaded. Now, i'm getting a LazyInitialization exception stating that the transaction has ended. To me this makes sense, of course the transaction should be over by now. The thing is, how can the assoicated set ever be lazy loaded if the transaction is over?
Entity Classes:
#Entity
public class LearningEntry implements Serializable {
private Long id;
String imagePath = "";
Set<Sample> samples = null;
//------------------------------
// Constructors
//------------------------------
public LearningEntry(){
imagePath = "";
samples = new HashSet<Sample>();
}
//------------------------------
// Instance Methods
//------------------------------
public void addSample(Sample s){
samples.add(s);
}
public void removeSample(Sample s){
samples.remove(s);
}
//------------------------------
// Setters and Getters
//------------------------------
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
//#Column(name = "wisi_LE_IMAGEPATH", length = 100, nullable = false)
public String getImagePath() {
return imagePath;
}
public void setImagePath(String imagePath) {
this.imagePath = imagePath;
}
// TODO - ONly works with fetch type EAGER
//#OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
#OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
public Set<Sample> getSamples() {
return samples;
}
public void setSamples(Set<Sample> samples) {
this.samples = samples;
}
}
Sample Entity
#Entity
public class Sample implements Serializable {
private Long id;
Date creationDate;
String audioFileLocation;
Integer votes;
String description;
public Sample(){
creationDate = new Date();
audioFileLocation = "";
votes = 0;
description = "";
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getAudioFileLocation() {
return audioFileLocation;
}
public void setAudioFileLocation(String audioFileLocation) {
this.audioFileLocation = audioFileLocation;
}
#Temporal(TemporalType.DATE)
public Date getCreationDate() {
return creationDate;
}
public void setCreationDate(Date creationDate) {
this.creationDate = creationDate;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Integer getVotes() {
return votes;
}
public void setVotes(Integer votes) {
this.votes = votes;
}
}
DAO Classes:
LearningEntryDAO
#Transactional
public class JpaLearningEntryDAO implements LearningEntryDAO{
private JpaTemplate jpaTemplate;
public JpaLearningEntryDAO(){
}
public void setJpaTemplate(JpaTemplate jpaTemplate){
this.jpaTemplate = jpaTemplate;
}
#Override
//#Transactional
public void delete(Long leId) {
LearningEntry dp = jpaTemplate.find(LearningEntry.class, leId);
jpaTemplate.remove(dp);
}
#Override
#SuppressWarnings("unchecked")
//#Transactional
public List<LearningEntry> findAll() {
return jpaTemplate.find("from LearningEntry");
}
#Override
//#Transactional
public LearningEntry findById(Long leId) {
return jpaTemplate.find(LearningEntry.class, leId);
}
#Override
//#Transactional
public LearningEntry store(LearningEntry dp) {
return jpaTemplate.merge(dp);
}
#Override
#SuppressWarnings("unchecked")
//#Transactional
public void deleteAll(){
throw new RuntimeException("deleteAll not implemented");
}
}
Sample DAO
#Transactional
public class JpaSampleDAO implements SampleDAO{
private JpaTemplate jpaTemplate;
public JpaSampleDAO(){}
public void setJpaTemplate(JpaTemplate jpaTemplate){
this.jpaTemplate = jpaTemplate;
}
#Override
//#Transactional
public void delete(Long sampleId) {
Sample dp = jpaTemplate.find(Sample.class, sampleId);
jpaTemplate.remove(dp);
}
#Override
#SuppressWarnings("unchecked")
public List<Sample> findAll() {
return jpaTemplate.find("from Sample");
}
#Override
public Sample findById(Long sampleId) {
return jpaTemplate.find(Sample.class, sampleId);
}
#Override
public Sample store(Sample dp) {
return jpaTemplate.merge(dp);
}
#Override
#SuppressWarnings("unchecked")
public void deleteAll(){
throw new RuntimeException("deleteAll not implemented");
}
}
Controller
#RequestMapping(value = "/index.htm", method = RequestMethod.GET)
public ModelAndView sayHello(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
Map<String, Object> model = new HashMap<String, Object>();
List<LearningEntry> le = learningEntryService.getLearningEntries();
model.put("learningEntries", le);
return new ModelAndView("main", model);
}
View
<section id="content" class="body">
<ol id="posts-list" class="hfeed">
<c:forEach items="${learningEntries}" var="learningEntry">
<li>
<table class="wisiEntry">
<tr>
<td class="pictureCell">
<img class="wisiEntry-pic" src="${learningEntry.imagePath}" />
</td>
<td class="previousNextCell"
<div class="wisiEntry-nextSampleButton">Next</div>
<div class="wisiEntry-previousSampleButton">Previous</div>
<br />
<div class="wisiEntry-addTagButton">Tag</div>
<div class="wisiEntry-addCommentButton">Comment</div>
<br />
<div class="wisiEntry-uploadButton">Upload</div>
</td>
<td>
<!-- ERROR HAPPENS HERE. Samples should not be null -->
<c:forEach items="${learningEntry.samples}" var="sample" varStatus = "status">
<table class="sampleEntry" ${status.first ? '' : 'style = "display:none"'}>
<tr>
<td class="sampleCell">
<p class="description">
${sample.description}
</p>
<audio src="${sample.audioFileLocation}" controls>
Your browser does not support the <code>audio</code> element.
</audio>
</td>
<td class="voteCell">
<img class="upVote" src="/images/upArrow.jpeg" />
<span class="voteNumber">${sample.votes}</span>
<img class="downVote" src="/images/downArrow.jpeg" />
</td>
</tr>
</table>
</c:forEach>
</td>
</tr>
</table>
</li>
</c:forEach>
</ol><!-- /#posts-list -->
</section><!-- /#content -->
I hope you are using findAll() method down the call. You can load all the associated samples by modifying your method like below.
public List<LearningEntry> findAll() {
List<LearningEntry> entries = jpaTemplate.find("from LearningEntry");
for(LearningEntry entry : entries){
entry.getSamples().size();
}
return entries;
}
Or, as you already know, you can also achieve this by changing fetch to FetchType.EAGER. But this might not suit you in all cases. Therefore, former way is better.
Or you might like to do no change anywhere, and define another method to get all the samples based on LearningEntry, this way you will be able to fire up an AJAX call on some event. But that might not suit here in this case.
Thanks to Vinegar for providing a working answer (upvoted).
I decided to add this answer that has also worked for me. I took this approach because I may want to make separate ajax calls in the future. In other words, I can ask for the LearningEntry in one transaction, than ask for its samples some time down the road.
#Transactional
public Set<Sample> getSamplesForLearningEntry(LearningEntry le) {
// Reload the le from the database so it is not transient:
LearningEntry le = leDAO.store(le);
le.getSamples.size();
return le.getSamples();
}
Most frameworks offer the 'open session in view' pattern. See https://www.hibernate.org/43.html:
The solution, in two-tiered systems,
with the action execution, data access
through the Session, and the rendering
of the view all in the same virtual
machine, is to keep the Session open
until the view has been rendered.
For data that is read often and hardly ever updated, query caching can help too. This reduces the load on the database, but increases memory usage. Hibernate can be configured to do this for you.

Categories

Resources