I have made a spring boot application connected to an angular front end. When the user enters a value into attendance id and hits submit on the form, this calls a method that updates the current value in the database using a HTTP PUT request.
However, the value is not being update despite break points showing the new value is being received and updated.
I am new to spring boot so any help is appreciated.
package com.example.demo.Attendance;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.transaction.Transactional;
import com.example.demo.AttendancePK.AttendancePK;
import com.example.demo.AttendanceType.AttendanceType;
import com.example.demo.LessonRun.LessonRun;
import com.fasterxml.jackson.annotation.JsonIgnore;
#Transactional
#Entity
public class Attendance {
#EmbeddedId
private AttendancePK id;
#ManyToOne
#JoinColumn(name="attendance_type", insertable = false, updatable=false)
private AttendanceType attendanceType;
#ManyToOne
#JsonIgnore
#JoinColumn(name="lesson_run_id", insertable = false, updatable=false)
private LessonRun lessonRun;
public LessonRun getLessonRun() {
return lessonRun;
}
public void setLessonRun(LessonRun lessonRun) {
this.lessonRun = lessonRun;
}
public AttendanceType getAttendanceType() {
return attendanceType;
}
public void setAttendanceType(AttendanceType attendanceType) {
this.attendanceType = attendanceType;
}
public Attendance(AttendancePK id, AttendanceType attendanceType, LessonRun lessonRun) {
super();
this.id = id;
this.attendanceType = attendanceType;
this.lessonRun = lessonRun;
}
public Attendance() {
}
public AttendancePK getId() {
return id;
}
public void setId(AttendancePK id) {
this.id = id;
}
}
My controller
#RequestMapping(value="/attendance/{attendanceId}/student/{studentId}/lessonrun/{lessonRunId}",method = RequestMethod.PUT)
public void updateAttendance(#PathVariable int attendanceId, #PathVariable int studentId, #PathVariable int lessonRunId, #RequestBody int attendanceTypeId) {
AttendancePK id = new AttendancePK(attendanceId, studentId,lessonRunId);
Attendance attendanceInDB = attendanceService.getAttendancebyId(id);
// attendanceInDB.setAttendanceType(int.getAttendanceType());
attendanceService.updateAttendance(attendanceInDB, attendanceTypeId);
}
My Service
package com.example.demo.Attendance;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.example.demo.AttendancePK.AttendancePK;
import com.example.demo.AttendanceType.AttendanceType;
import com.example.demo.AttendanceType.AttendanceTypeRepository;
#Service
public class AttendanceService {
#Autowired
private AttendanceRepository attendanceRepository;
#Autowired
private AttendanceTypeRepository attendanceTypeRepository;
public List<Attendance> getAllAttendanceRecs() {
List<Attendance> attendanceList = new ArrayList<>();
attendanceRepository.findAll().forEach(attendanceList::add);
return attendanceList;
}
public Attendance getAttendancebyId(AttendancePK id) {
Optional<Attendance> optionalAttendance = attendanceRepository.findById(id);
if (optionalAttendance.isPresent()) {
return optionalAttendance.get();
}
return null;
}
public void updateAttendance(Attendance attendanceInDB, int attendanceTypeId) {
Optional<AttendanceType> attendanceType = attendanceTypeRepository.findById(attendanceTypeId);
if (attendanceType.isPresent()) {
attendanceInDB.setAttendanceType(attendanceType.get());
attendanceRepository.save(attendanceInDB);
}
}
}
the breakpoint results show the value is updated shown here
but MySQL database doesn't reflect this
Related
I have started learning Spring Boot recently.
I am trying to Soft delete the user. I want to soft delete all the Notes of the user when I soft delete the User. But my code is only soft deleting the user, not its notes.
When I am doing soft delete only on notes table, it's working fine but on User Entity, it is only deleting the user.
Notes
package com.we.springmvcboot.Model;
import java.sql.Date;
import java.util.ArrayList;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;
import com.fasterxml.jackson.annotation.JsonIgnore;
#Entity
#Table(name="Notes")
#Where(clause = "deleted = 'false'")//FALSE
public class Notes {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="NotesID")
private long NotesID;
#Column(name="Title")
private String Title;
#Column(name="Message")
private String Message;
#Column(name="Date")
private String date;
#Column(name="deleted")
private String deleted="false";
#Column(name="label")
private int label=1;
#ManyToOne()
#JoinColumn(name = "UserID", nullable = false)
private User user;
public Notes() {}
public String getDeleted() {
return deleted;
}
public void setDeleted(String deleted) {
this.deleted = deleted;
}
public Notes(String title, String message, String date, User user, int label) {
super();
Title = title;
Message = message;
this.date = date;
this.user = user;
this.label=label;
}
public Notes(long notesID, String title, String message, String date, int label) {
super();
NotesID = notesID;
Title = title;
Message = message;
this.date = date;
this.label=label;
}
public int getLabel() {
return label;
}
public void setLabel(int label) {
this.label = label;
}
public long getNotesID() {
return NotesID;
}
public void setNotesID(long notesID) {
NotesID = notesID;
}
public String getTitle() {
return Title;
}
public void setTitle(String title) {
Title = title;
}
public String getMessage() {
return Message;
}
public void setMessage(String message) {
Message = message;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public void setUser(User user) {
this.user = user;
}
}
User
package com.we.springmvcboot.Model;
import java.util.ArrayList;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.annotations.Where;
import antlr.collections.List;
#Entity
#Table(name="User")
#Where(clause = "deleted = 'false'")//FALSE
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long UserID;
#Column(name="emailid")
private String emailID;
#Column(name="deleted")
private String deleted="false";
#OneToMany(mappedBy="user", fetch = FetchType.EAGER,cascade=CascadeType.ALL, orphanRemoval=true)
private Set<Notes> usernotes;
public User() {}
public User(String emailID) {
super();
this.emailID = emailID;
}
public long getUserID() {
return UserID;
}
public void setUserID(long userID) {
UserID = userID;
}
public String getemailID() {
return emailID;
}
public void setemailID(String emailID) {
emailID = emailID;
}
public Set<Notes> getUsernotes() {
return usernotes;
}
public void setUsernotes(Set<Notes> usernotes) {
this.usernotes = usernotes;
}
}
NotesRepository
package com.we.springmvcboot.Repository;
import java.sql.Date;
import java.util.List;
import javax.transaction.Transactional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import com.we.springmvcboot.Model.Notes;
#Repository
public interface NotesRepository extends JpaRepository<Notes, Long> {
#Query("update Notes e set e.deleted='true' where e.NotesID=?1")
#Transactional
#Modifying
public void softDelete(long id);
}
UserRepository
package com.we.springmvcboot.Repository;
import java.sql.Date;
import java.util.List;
import javax.transaction.Transactional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import com.we.springmvcboot.Model.Notes;
import com.we.springmvcboot.Model.User;
#Repository
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByEmailID(String email);
#Query("update User e set e.deleted='true', where e.UserID=?1")
#Transactional
#Modifying
public void softDelete(long id);
}
TodoService
package com.we.springmvcboot.Service;
import com.we.springmvcboot.Model.*;
import com.we.springmvcboot.exception.*;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;
import com.we.springmvcboot.Repository.NotesRepository;
import com.we.springmvcboot.Repository.UserRepository;
#Service
public class TodoService {
#Autowired
UserRepository userrepo;
#Autowired
NotesRepository notesrepo;
public Object deleteUser(Map<String, Object> input) {
long userID;
userID = ((Number) input.get("userID")).longValue();
userrepo.softDelete(userID);
return null;
}
}
I would suggest that you read this post for the simplest approach to soft delete. You should arrive at sth like the following:
#SQLDelete("UPDATE User SET deleted = TRUE WHERE id = ?")
#Where(clause = "deleted = FALSE")
public class User {
#OneToMany(mappedBy = "user", fetch = EAGER, cascade=ALL, orphanRemoval = true)
private Set<Notes> usernotes;
...
}
#SQLDelete("UPDATE Note SET deleted = TRUE WHERE id = ?")
#Where(clause = "deleted = FALSE")
public class Note {...}
The above will work if you use the following code to delete a User:
public Object deleteUser(Map<String, Object> input) {
long userID;
userID = ((Number) input.get("userID")).longValue();
User user = userrepo.deleteById(userID);
return null;
}
If you want to keep using the custom query, though, you still need to call a separate query to delete Notes by userId, because Cascade.REMOVE will not be triggered in this case. In other words, you'll want a method like:
public interface NotesRepository extends JpaRepository<Notes, Long> {
#Query("UPDATE Notes n SET n.deleted = TRUE WHERE n.user.id = :id")
public void deleteByUserId(long id);
}
which you then call from deleteUser:
long userID;
userID = ((Number) input.get("userID")).longValue();
userrepo.softDelete(userID);
noteRepo.deleteByUserId(userID);
return null;
I have developped a Spring boot application that was using fetch = EAGER annotation on all relationships between entities. I think this is causing severe performance issues and I've since learned that it is seemingly an anti-pattern (https://vladmihalcea.com/the-open-session-in-view-anti-pattern/ & https://vladmihalcea.com/eager-fetching-is-a-code-smell/).
I've been trying to figure out how to use lazy loading properly. I've come up with a minimal example that allows me to reproduce it.
TestJpaApplication
package com.myproject.testJpa;
import com.myproject.testJpa.entity.Host;
import com.myproject.testJpa.entity.HostSet;
import com.myproject.testJpa.entity.repository.HostRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import com.myproject.testJpa.entity.repository.HostSetRepository;
import org.springframework.transaction.annotation.Transactional;
#SpringBootApplication
public class TestJpaApplication {
private final Logger logger = LoggerFactory.getLogger(TestJpaApplication.class);
#Autowired
private HostRepository hostRepository;
#Autowired
private HostSetRepository hostSetRepository;
public static void main(String[] args) {
SpringApplication.run(TestJpaApplication.class, args);
}
#Bean
public CommandLineRunner demo() {
return (args) -> {
init();
fetch();
};
}
private void init() {
Host host1 = findOrCreateHost("HOST 1");
Host host2 = findOrCreateHost("HOST 2");
Host host3 = findOrCreateHost("HOST 3");
HostSet hostSet = findOrCreateHostSet("HOST SET 1");
hostSet.addHost(host1);
hostSetRepository.save(hostSet);
hostRepository.save(host1);
hostRepository.save(host2);
hostRepository.save(host3);
}
#Transactional
private void fetch() {
HostSet hostSet = hostSetRepository.findOneByNameIgnoreCase("HOST SET 1");
for(Host host : hostSet.getHosts()) {
logger.debug("Host: {}", host);
}
}
public Host findOrCreateHost(String name) {
Host host = hostRepository.findOneByNameIgnoreCase(name);
if(host == null) {
host = new Host(name);
hostRepository.save(host);
}
return host;
}
public HostSet findOrCreateHostSet(String name) {
HostSet hostSet = hostSetRepository.findOneByNameIgnoreCase(name);
if (hostSet == null) {
hostSet = new HostSet(name);
hostSetRepository.save(hostSet);
}
logger.debug("Host: {}", hostSet.getHosts());
return hostSet;
}
}
Host
package com.myproject.testJpa.entity;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
#Entity
public class Host {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "host__id")
private Long id;
private String name;
#ManyToMany(mappedBy = "hosts")
private Set<HostSet> hostSets = new HashSet<>();
public Host() {
}
public Host(Long id) {
this.id = id;
}
public Host(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<HostSet> getHostSets() {
return hostSets;
}
public void setHostSets(Set<HostSet> hostSets) {
this.hostSets = hostSets;
hostSets.forEach(hs -> addToHostSet(hs));
}
public Host addToHostSet(HostSet hostSet) {
if (!hostSets.contains(hostSet)) {
hostSets.add(hostSet);
hostSet.getHosts().add(this);
}
return this;
}
public Host removeFromHostSet(HostSet hostSet) {
if (hostSets.contains(hostSet)) {
hostSets.remove(hostSet);
hostSet.getHosts().remove(this);
}
return this;
}
}
HostSet
package com.myproject.testJpa.entity;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
#Entity
public class HostSet {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "host_set__id")
private Long id;
private String name;
#ManyToMany
#JoinTable(
name = "host_set__host",
joinColumns = #JoinColumn(name = "host_set__id"),
inverseJoinColumns = #JoinColumn(name = "host__id")
)
private Set<Host> hosts = new HashSet<>();
public HostSet() {
}
public HostSet(Long id) {
this.id = id;
}
public HostSet(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Host> getHosts() {
return hosts;
}
public void setHosts(Set<Host> hosts) {
this.hosts = hosts;
}
public HostSet addHost(Host host) {
if(!hosts.contains(host)) {
hosts.add(host);
host.addToHostSet(this);
}
return this;
}
public HostSet removeHost(Host host) {
if(hosts.contains(host)) {
hosts.remove(host);
host.removeFromHostSet(this);
}
return this;
}
}
HostRepository
package com.myproject.testJpa.entity.repository;
import com.myproject.testJpa.entity.Host;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface HostRepository extends JpaRepository<Host, Long> {
public Host findOneByNameIgnoreCase(String name);
}
HostSetRepository
package com.myproject.testJpa.entity.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.myproject.testJpa.entity.HostSet;
#Repository
public interface HostSetRepository extends JpaRepository<HostSet, Long> {
public HostSet findOneByNameIgnoreCase(String name);
}
When I run the application, it throws the following error when looping over the hosts of the retrieved hostSet in the fetch() method.
Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.myproject.testJpa.entity.HostSet.hosts, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:606)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:218)
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:585)
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:149)
at org.hibernate.collection.internal.PersistentSet.iterator(PersistentSet.java:188)
at com.myproject.testJpa.TestJpaApplication.fetch(TestJpaApplication.java:58)
at com.myproject.testJpa.TestJpaApplication.lambda$demo$0(TestJpaApplication.java:34)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:784)
I've tried adding the #Transactional annotation in several places but to no avail. It's driving me crazy because I don't see what I'm doing wrong.
Thanks for your help!
It turns out that the #Transactional was not working in the TestJpaApplication class (I did not set it on the anonymous method, don't know how or if it's possible).
I moved the content to a separate service and it worked.
I'm facing some problem with displaying COUNT of a variable while querying a MySQL database. I have made a variable with annotation #Transient so that it's not included in the DB. But, I'm getting error while posting data in the same table in the DB, since while posting, there is no field count, count is only used to get COUNT(u_type). Is there any way with which I can display COUNT of a variable when I do a GET call (using SQL query) and no need to post it. TIA.
Class:
import java.sql.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import org.springframework.data.annotation.Transient;
#Entity // This tells Hibernate to make a table out of this class
public class UserClickData {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private String u_search_term;
private String u_sysid;
private String u_type;
#Transient
private long count;
public UserClickData(String u_type, long Count) { //, long count
this.u_type = u_type;
this.count=count;
}
public long getCount() {
return count;
}
public void setCount(long count) {
this.count=count;
}
public int getSys_id() {
return sys_id;
}
public void setSys_id(int sys_id) {
this.sys_id = sys_id;
}
public String getU_search_term() {
return u_search_term;
}
public void setU_search_term(String u_search_term) {
this.u_search_term = u_search_term;
}
public String getU_type() {
return u_type;
}
public void setU_type(String u_type) {
this.u_type = u_type;
}
}
Projection:
public interface UserClickProjection {
String getU_type();
long getCount();
}
DAO Code:
import java.util.List;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import com.abc.datacollection.entity.UserClickData;
import com.abc.datacollection.entity.UserClickProjection;
import com.abc.datacollection.entity.UserProjection;
public interface UserClickDataRepository extends CrudRepository<UserClickData, Integer> {
public static final String FIND_QUERY =
"select new com.abc.datacollection.entity.UserClickData(user.u_type, COUNT(u_type)) from UserClickData user GROUP BY user.u_type ORDER BY COUNT(user.u_type) DESC";
#Query(value = FIND_QUERY)
//public List<UserProjection> getAllRequestResponseRecords();
List<UserClickProjection> findAllProjectedBy();
}
Controller:
#CrossOrigin(origins = "*")
#GetMapping(path="/all")
public #ResponseBody List<UserClickProjection> getAllUserClickDataRecords() {
return userClickDataRepository.findAllProjectedBy();
}
Import javax.persistence.Transient instead of org.springframework.data.annotation.Transient
Today I did some experiments with hibernate. Unfortunately it seems if I’m misunderstanding something about the sessions.
I have three entities (book “buch”, user “benutzer” and rent “leihstellung”).
Each book knows about the rents, it’s concerned by. Each rent knows about the associated book. Furthermore each rent knows about the fitting user and of course each user knows the associated rents.
I explicitly want to have this two way mappings.
Now I wrote a small tester which inserts some data. The insert progress works as expected. After inserting some data I would like to delete a user.
If I do this before the commit, hibernate gives me an error, because the user will be reinserted be the rents it belongs to (that even happens, if I manually delete the user from this rents). Here I don’t really understand why that happens.
Everything works fine, if I do a session.close and open a new session for deleting the user.
I guess, that there is a smarter way to do this within one session. But unfortunately I don’t know how this can be done.
Any explanation is welcome.
public class Worker implements Iworker{
private Sessiongetter sg;
private MainMenu mm;
public void work(File datei)
{
sg = new Sessiongetter();
Session session = sg.getSesseion();
WlBuchart wlBuchart = new WlBuchart(1, "Sachbuch");
Buch buch = new Buch("test", "ich", 1);
buch.setWlBuchart(wlBuchart);
Buch buch2 = new Buch("versuch", "du",2);
buch2.setWlBuchart(wlBuchart);
session.beginTransaction();
session.save(wlBuchart);
session.save(buch);
session.save(buch2);
Benutzer benutzer = new Benutzer("hans", "dampf", "Lehrer", "versuch");
session.save(benutzer);
Leihstellung leihstellung = new Leihstellung(benutzer, buch);
Leihstellung leihstellung2 = new Leihstellung(benutzer, buch2);
session.save(leihstellung);
session.save(leihstellung2);
benutzer.addLeihstellung(leihstellung);
benutzer.addLeihstellung(leihstellung2);
session.update(benutzer);
buch.addLeihstellung(leihstellung);
buch2.addLeihstellung(leihstellung2);
session.update(buch);
session.update(buch2);
session.remove(benutzer);
session.flush();
session.getTransaction().commit();
session.close();
System.out.println("fertig");
}
package code.logik;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.Session;
#Entity
#Table(name="benutzer")
public class Benutzer {
#Column(nullable=false)
private String vorname, nachname, gruppe;
#Id
private String kennung;
private boolean admin;
#Column(nullable=true)
private String kennwort;
#OneToMany(cascade=CascadeType.ALL, mappedBy="benutzer")
private List<Leihstellung>leihstellungs;
public String getKennwort() {
return kennwort;
}
public void setKennwort(String kennwort) {
this.kennwort = kennwort;
}
public Benutzer(String vorname, String nachname, String gruppe, String kennung) {
this.vorname=vorname;
this.nachname=nachname;
this.gruppe=gruppe;
this.kennung=kennung;
this.leihstellungs= new ArrayList<>();
}
public Benutzer() {
// TODO Auto-generated constructor stub
}
public String getVorname() {
return vorname;
}
public String getNachname() {
return nachname;
}
public String getGruppe() {
return gruppe;
}
public String getKennung() {
return kennung;
}
public boolean isAdmin() {
return admin;
}
public void setAdmin(boolean admin) {
this.admin = admin;
}
public List<Leihstellung> getLeihstellungs() {
return leihstellungs;
}
public void addLeihstellung(Leihstellung leihstellung)
{
leihstellungs.add(leihstellung);
}
public int compare(Benutzer other)
{
if (this.getNachname().compareTo(other.getNachname())!=0)
{
return this.getNachname().compareTo(other.getNachname());
}
return this.getVorname().compareTo(other.getVorname());
}
}
package code.logik;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.annotations.ManyToAny;
#Entity
#Table(name="buch")
public class Buch {
#Column(nullable=false)
private String titel;
private String autor;
#ManyToOne
private WlBuchart wlBuchart;
#OneToMany(cascade=CascadeType.ALL, mappedBy="buch")
private List<Leihstellung>leihstellungs;
public WlBuchart getWlBuchart() {
return wlBuchart;
}
public void setWlBuchart(WlBuchart wlBuchart) {
this.wlBuchart = wlBuchart;
}
#Id
private int nummer;
public Buch(String titel, String autor,int nummer) {
this.titel=titel;
this.autor=autor;
this.nummer=nummer;
leihstellungs = new ArrayList<>();
}
public Buch() {
// TODO Auto-generated constructor stub
}
public String getTitel() {
return titel;
}
public String getAutor() {
return autor;
}
public int getNummer() {
return nummer;
}
public List<Leihstellung> getLeihstellungs() {
return leihstellungs;
}
public void addLeihstellung(Leihstellung leihstellung)
{
leihstellungs.add(leihstellung);
}
}
package code.logik;
import java.time.LocalDate;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
#Entity
#Table(name="leihstellung")
public class Leihstellung {
#ManyToOne
private Benutzer benutzer;
#Id #GeneratedValue
private int id;
#Column(nullable=false)
private LocalDate von;
private LocalDate bis;
#ManyToOne
private Buch buch;
public Leihstellung(Benutzer benutzer, Buch buch) {
this.benutzer=benutzer;
this.buch=buch;
this.von = LocalDate.now();
}
public Leihstellung() {
// TODO Auto-generated constructor stub
}
public void setAbgegeben()
{
bis = LocalDate.now();
}
public Benutzer getBenutzer() {
return benutzer;
}
public int getId() {
return id;
}
public LocalDate getVon() {
return von;
}
public LocalDate getBis() {
return bis;
}
public Buch getBuch() {
return buch;
}
}
Found the solution myself. I had to delete the references from the connected rents and books.
Now everything works find.
I am developing Spring Boot app with Spring Data JPA and H2 database. I was writing my model entity classes and I got to the moment where I need to make ManyToMany relationship between FreetimeActivity and Goal entities. In Goal class I have collection of Goalable objects. Goalable is my interface. This interface is implemented by 3 classes. I want objects of any of this classes to be stored in that collection. FreetimeActivity is one of them (but the only implemented so far). Can Spring Data make some magic and make that kind of relationship for me or do I have to make separate colletion for all of these 3 classes and merge them into one interface type collection in the end?
I tried with #ManyToMany and #JoinColumn annotations and added some testing code to starting class, but when run It throws an exception:
#OneToMany or #ManyToMany targeting an unmapped class: com.github.mesayah.assista.model.Goal.activityList[com.github.mesayah.assista.model.Goalable]
Are there any annotations that can make that for me?
FreetimeActivity.java
package com.github.mesayah.assista.model;
import javax.persistence.*;
import java.util.List;
/**
* Created by Mesayah on 03.07.2017.
*/
#Entity
#Table(name = "freetime_activity")
public class FreetimeActivity extends Activity {
#Id
#GeneratedValue
private long id;
private String name;
#ManyToMany(mappedBy = "freetime_activities")
private List<Goal> goals;
#Override
public long getId() {
return id;
}
#Override
public void setId(long id) {
this.id = id;
}
#Override
public String getName() {
return name;
}
#Override
public void setName(String name) {
this.name = name;
}
public List<Goal> getGoals() {
return goals;
}
public void setGoals(List<Goal> goalList) {
this.goals = goalList;
}
public FreetimeActivity(String name) {
this.name = name;
}
}
Goal.java
package com.github.mesayah.assista.model;
import javax.persistence.*;
import java.util.List;
/**
* Created by Mesayah on 02.07.2017.
*/
#Entity
public class Goal {
#Id
#GeneratedValue
private long id;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(name = "goal_freetime_activity", joinColumns = #JoinColumn(name = "goal_id", referencedColumnName =
"id"),
inverseJoinColumns = #JoinColumn(name = "freetime_activity_id", referencedColumnName = "id"))
private List<FreetimeActivity> activityList;
private List<Milestone> milestoneList;
public Goal() {
}
public Goal(List<FreetimeActivity> activityList) {
this.activityList = activityList;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public List<FreetimeActivity> getActivityList() {
return activityList;
}
public void setActivityList(List<FreetimeActivity> activityList) {
this.activityList = activityList;
}
public List<Milestone> getMilestoneList() {
return milestoneList;
}
public void setMilestoneList(List<Milestone> milestoneList) {
this.milestoneList = milestoneList;
}
}
AssistaApplication.java
package com.github.mesayah.assista;
import com.github.mesayah.assista.model.Course;
import com.github.mesayah.assista.model.Exam;
import com.github.mesayah.assista.repository.CourseRepository;
import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.transaction.annotation.Transactional;
import javax.sql.DataSource;
import java.util.List;
#SpringBootApplication
#EnableJpaRepositories("com.github.mesayah.assista.model")
public class AssistaApplication {
private final static Logger logger = LoggerFactory.getLogger(AssistaApplication.class);
public static void main(String[] args) {
SpringApplication.run(AssistaApplication.class, args);
}
#Bean
#Transactional
public CommandLineRunner commandLineRunner(CourseRepository courseRepository, ExamRepository examRepository) {
return (args) -> {
Course course = new Course("Dancing Course");
Exam exam = new Exam("Dancing Test", course);
// testing save
courseRepository.save(course);
examRepository.save(exam);
course.getGrades().add(4.0);
course.getGrades().add(4.5d);
course.getGrades().add(3.5d);
// testing update
courseRepository.save(course);
// using Spring Data JPA automated repositories
List<Course> courses = (List<Course>) courseRepository.findAll();
List<Exam> result = examRepository.findByCourse(course);
Exam theExam = result.get(0);
// testing relations
logger.info("Courses in database: " + courses.size() + "\nExam's Course Id: " + theExam.getCourse().getId() + "\nCourse grades: " + theExam.getCourse().getGrades());
};
}
#Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).build();
}
}