I am working on a Spring MVC app in which there are two model classes: LocationModel and ContactModel. Below is the code:
#Entity
#Table(name="Contact")
public class ContactModel {
#Id
#Column(name="contactid")
#GeneratedValue
private int contactId;
#Column(name="contactname")
private String contactName;
#Column(name="contactemail")
private String email;
#Column(name="contactphone")
private String phone;
#ManyToOne
#JoinColumn(name="locationid")
private LocationModel locationModel;
}
#Entity
#Table(name="Location")
public class LocationModel {
#Id
#Column(name="locationid")
#GeneratedValue
private int locationId;
#Column(name="locationname")
private String locationName;
#Column(name="locationdesc")
private String locationDescription;
#Column(name="type")
private String locationType;
#Column(name="address")
private String address;
#Column(name="state")
private String state;
#Column(name="circle")
private int circle;
#Column(name="district")
private int district;
#Column(name="town")
private int town;
#Column(name="lattitude")
private String lattitude;
#Column(name="longitude")
private String longitude;
#Column(name="locationuid")
private String locationUID;
#Column(name="category")
private String category;
#Column(name="bedcount")
private int bedCount;
#OneToMany(mappedBy = "locationModel", fetch = FetchType.EAGER)
private List<ContactModel> contactList;
}
Primary key in location table is foreign key in contact table. I have 2 records in contact table, with location id 0.
I am using following code for getting contact list:
Session session = sessionFactory.getCurrentSession();
Query query = session
.createQuery("from ContactModel where contactName like :contactName");
return query.setParameter("contactName", contactName + "%").list();
But it shows exception:
Error performing load command : org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.bizmerlin.scm.model.LocationModel#0]
17:03:31,135 ERROR [stderr] (http--127.0.0.1-9090-2) org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.bizmerlin.scm.model.LocationModel#0]
17:03:31,139 ERROR [stderr] (http--127.0.0.1-9090-2) at org.hibernate.internal.SessionFactoryImpl$1$1.handleEntityNotFound(SessionFactoryImpl.java:247)
17:03:31,141 ERROR [stderr] (http--127.0.0.1-9090-2) at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:214)
17:03:31,143 ERROR [stderr] (http--127.0.0.1-9090-2) at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:264)
Perhaps it is due to that fact that location table has no record with location id 0. If so, how can I get contact list, even if their location is null?
Use optional attribute
#ManyToOne(optional=true)
#JoinColumn(name="locationid")
private LocationModel locationModel;
http://learningviacode.blogspot.in/2011/12/one-to-many-assocition-that-is-optional.html
Related
I'm having trouble with a many to many relation with JPA.
My code looks as follows:
The Sensor class:
#Entity
#Table(name = "sensor")
#Data
#NoArgsConstructor
#AllArgsConstructor
public class Sensor {
#Id
private long chipId;
#OneToMany(mappedBy = "sensor")
#JsonBackReference
private Set<Link> userLinks;
private String firmwareVersion;
private long creationTimestamp;
private String notes;
private long lastMeasurementTimestamp;
private long lastEditTimestamp;
private double gpsLatitude;
private double gpsLongitude;
private double gpsAltitude;
private String country;
private String city;
private boolean indoor;
private boolean published;
}
The user class:
#Entity
#Table(name = "user")
#Data
#NoArgsConstructor
#AllArgsConstructor
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#JsonManagedReference
private int id;
private String firstName;
private String lastName;
private String email;
private String password;
#OneToMany(mappedBy = "user")
private Set<Link> sensorLinks;
private int role;
private int status;
private long creationTimestamp;
private long lastEditTimestamp;
}
And the Link class (relation class):
#Entity
#Table(name = "link")
#Data
#AllArgsConstructor
#NoArgsConstructor
public class Link {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#ManyToOne
#JoinColumn(name = "user_id")
#MapsId("user_id")
private User user;
#ManyToOne
#JoinColumn(name = "sensor_id")
#MapsId("sensor_id")
private Sensor sensor;
private boolean owner;
private String name;
private int color;
private long creationTimestamp;
}
The controller:
...
#RequestMapping(method = RequestMethod.GET, path = "/user/{email}", produces = MediaType.APPLICATION_JSON_VALUE)
#ApiOperation(value = "Returns details for one specific user")
public User getUserByEmail(#PathVariable("email") String email) {
return userRepository.findByEmail(email).orElse(null);
}
...
The UserRepository:
public interface UserRepository extends JpaRepository<User, Integer> {
Optional<User> findByEmail(String email);
#Modifying
#Query("UPDATE User u SET u.firstName = ?2, u.lastName = ?3, u.password = ?4, u.role = ?5, u.status = ?6 WHERE u.id = ?1")
Integer updateUser(int id, String firstName, String lastName, String password, int role, int status);
}
I want to achieve, that the user endpoint shows all linked sensors with that particular user.
What I get is only an error message:
JSON mapping problem:
com.chillibits.particulatematterapi.model.db.main.User["sensorLinks"];
nested exception is
com.fasterxml.jackson.databind.JsonMappingException: Infinite
recursion (StackOverflowError) (through reference chain:
com.chillibits.particulatematterapi.model.db.main.User["sensorLinks"])
How can I fix this issue?
Thanks in advance
Marc
------------------------------------ Edit -----------------------------------
According to Abinash Ghosh's answer, I added following DTOs:
UserDto:
#Data
#NoArgsConstructor
#AllArgsConstructor
public class UserDto {
private int id;
private String firstName;
private String lastName;
private Set<LinkDto> sensorLinks;
private int role;
private int status;
private long creationTimestamp;
private long lastEditTimestamp;
}
LinkDto:
#Data
#NoArgsConstructor
#AllArgsConstructor
public class LinkDto {
private Integer id;
private SensorDto sensor;
private boolean owner;
private String name;
private int color;
private long creationTimestamp;
}
And the mapper (I realized it a bit different, but it should be the same):
public UserDto getUserByEmail(#PathVariable("email") String email) {
User user = userRepository.findByEmail(email).orElse(null);
return convertToDto(user);
}
private UserDto convertToDto(User user) {
return mapper.map(user, UserDto.class);
}
This leads to following Exception:
2020-04-13 14:22:24.383 WARN 8176 --- [nio-8080-exec-2] o.h.e.loading.internal.LoadContexts : HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext#68ab57c7<rs=HikariProxyResultSet#2017009664 wrapping Result set representing update count of -1>
1) Error mapping com.chillibits.particulatematterapi.model.db.main.User to com.chillibits.particulatematterapi.model.io.UserDto
1 error] with root cause
java.lang.StackOverflowError: null
at com.mysql.cj.NativeSession.execSQL(NativeSession.java:1109) ~[mysql-connector-java-8.0.19.jar:8.0.19]
...
It's working!
This post helped: https://stackoverflow.com/a/57111004/6296634
Seems that you should not use Lombok #Data in such cases.
When User serialized for the response, all getter methods of User's fields are called.
So, User relational field sensorLinks's getter are also called to set value. This happened recursively. That's cause of infinite recursion.
It's better to not use Entity as a response. Create a DTO class for User then map User entity value into DTO then send response. Don't use any Enity class again into DTO then it will result same problem
For dynamically map one model to another you can use ModleMapper
public class UserDTO {
//Fields you want to show in response & don't use enity class
private Set<LinkDTO> sensorLinks;
}
public class LinkDTO{
//Fields you want to show in response &don't use enity class
}
public User getUserByEmail(#PathVariable("email") String email) {
User user = userRepository.findByEmail(email).orElse(null);
UserDTO userDto = merge(user,UserDTO.class)
return userDto;
}
public static <T> void merge(T source, T target) {
ModelMapper modelMapper = new ModelMapper();
modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
modelMapper.map(source, target);
}
hello I'm trying to make a rest API, by querying "where" based on date. I connect with postgresql.
I have an entity like this
#Entity
#Table(name ="device")
public class DeviceEntity {
#Column(name="updated")
private Date updated;
#Id
#GeneratedValue
#Column(name = "phone")
private String phone;
#Column(name = "accountid")
private String accountid;
#Column(name = "accountname")
private String accountname;
and this is my query:
#Repository
public interface DeviceRepository extends PagingAndSortingRepository {
#Query(value="SELECT * FROM device_data WHERE updated = ?1", nativeQuery = true)
Page<DeviceEntity> findByUserAndStatusOrderByCreatedAtDesc(Date updated, PageRequest pageRequest
);}
after running and test url, i'm getting error "bad value for type int : 8962101012749336481"
8962101012749336481 This is already beyond INT datatype
you should be using BIGINT
See DBFIDDLE
Various INT datatype in postgresql can be found here
I have problem with adding records to my junction table with JPA+Hibernate
when I try to add simple record with POST request it's throws me an error:
"message": "could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement"
And in my console:
MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails*
I had defined Join columns #JoinColumn(insertable=false, updatable=false) because it was demanding by Hibernate, otherwise it throws me an error that I should do that...
Here is my junction entity code:
#Entity
#Table(name = "hospital_doctor")
#IdClass(Hosdoc.class)
public class HospitalDoctor implements Serializable {
#Id
private int hospitalId;
#Id
private int doctorId;
// fields of hospitalDoctor table
#Temporal(TemporalType.DATE)
private Date contractStartDate;
#Temporal(TemporalType.DATE)
private Date contractEndDate;
private String position;
private String supervisor;
private boolean partTime;
#ManyToOne
#JoinColumn(name="HospitalId", insertable = false, updatable = false)
private Hospital hospital;
#ManyToOne
#JoinColumn(name="DoctorId", insertable = false, updatable = false)
private Doctor doctor;
// GETTERS AND SETTERS....
I wrote simple adding function in hospital class but I don't know how to use it to add record to junction table by POST request.
public void addDoctor(Doctor doctor, boolean partTime, Date contractEndDate, Date contractStartDate,
String position, String supervisor) {
HospitalDoctor association = new HospitalDoctor();
association.setDoctor(doctor);
association.setHospital(this);
association.setDoctorId(doctor.getId());
association.setHospitalId(this.getId());
association.setContractStartDate(contractStartDate);
association.setContractEndDate(contractEndDate);
association.setPosition(position);
association.setSupervisor(supervisor);
association.setPartTime(partTime);
doctors.add(association);
}
Service:
public void addHospitalDoctor(HospitalDoctor hospitalDoctor) {
hospitalDoctorDao.save(hospitalDoctor);
}
Controller:
#PostMapping(value = "/api/hospitaldoctors")
public void addHospitalDoctor(HospitalDoctor hospitalDoctor) {
hospitalDoctorService.addHospitalDoctor(hospitalDoctor);
}
I created a model RequisitionDetail.
It has some properties, such as: requisitionId (a foreign key on requisition table), productId (a foreign key on product table), quantity, unitPrice, totalPrice.
When I declare annotation #ManyToOne or #OneToOne and deploy the code, I have this error.
Without declared #ManyToOne or #OneToOne annotation my application is deployed Successfully.
How to solve this problem?
I Attach the Code Bellow :
Class Name: RequisitionDetail.java
#Entity
#Table(name = "requisition_details")
public class RequisitionDetail {
#Id
private Long id;
#ManyToOne(cascade = CascadeType.ALL)
#Column(name = "requisition_id")
private Long requisitionId;
#OneToOne
#Column(name = "product_id")
private Long productId;
private int quantity;
#Column(name = "unit_price")
private Double unitPrice;
#Column(name = "total_price")
private Double totalPrice;
}
when trying a search on some entities in the CRUD module of Play I'm getting this exception:
play.exceptions.JavaExecutionException: org.hibernate.exception.SQLGrammarException: could not execute query
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:290)
at Invocation.HTTP Request(Play!)
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not execute query
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1235)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1168)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:250)
at play.db.jpa.JPAPlugin$JPAModelLoader.fetch(JPAPlugin.java:431)
at controllers.CRUD$ObjectType.findPage(CRUD.java:253)
at controllers.CRUD.list(CRUD.java:36)
at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:413)
at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:408)
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:182)
... 1 more
Caused by: org.hibernate.exception.SQLGrammarException: could not execute query
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:92)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.loader.Loader.doList(Loader.java:2452)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2192)
at org.hibernate.loader.Loader.list(Loader.java:2187)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:452)
at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:363)
at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1258)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:241)
... 7 more
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'CHARSET' in 'where clause'
at com.mysql.jdbc.Util.handleNewInstance(Util.java:409)
at com.mysql.jdbc.Util.getInstance(Util.java:384)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1054)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3566)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3498)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1959)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2113)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2568)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2113)
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2275)
at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208)
at org.hibernate.loader.Loader.getResultSet(Loader.java:1869)
at org.hibernate.loader.Loader.doQuery(Loader.java:718)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:270)
at org.hibernate.loader.Loader.doList(Loader.java:2449)
... 15 more
The odd thing is that search works for some entities and not for others. For example, for the following entity adding any string in the search box works:
#Entity
public class Act extends Model {
#Transient
private static final int PAGE_SIZE = Integer.parseInt(Play.configuration.getProperty("pagination.size","10"));
#Required(message = "act.name.required")
public String name;
#Required(message = "act.description.required")
#Lob
#MaxSize(value=500, message="act.description.maxsize")
public String description;
public Blob image;
public boolean showInClosedMode;
#Temporal(TemporalType.TIMESTAMP)
public Date updated;
#Required(message = "act.theatre.required")
#ManyToOne
public Theatre theatre;
public boolean disabled;
#OneToMany(mappedBy="act")
public List<Offer> offers;
#ManyToMany(cascade=CascadeType.PERSIST)
public Set<Tag> tags;
#Transient
public String tagListSupport;
[... some methods ...]
}
But not for this one:
#Entity
public class User extends Model {
#Required(message = "user.name.required")
public String name;
#Email(message = "user.email.invalid")
public String email;
public String prefLang;
public Long prefCity;
public int credits;
public Date lastLogin;
#NoBinding("profile")
public boolean disabled;
#NoBinding("profile")
public boolean admin;
#NoBinding("profile")
public boolean anonymous;
#OneToMany(mappedBy = "owner")
public List<Ticket> tickets;
#ManyToMany
public List<Theatre> theatres;
public String googleId;
public String yahooId;
public String facebookId;
public String twitterId;
public String twitter_token;
public String twitter_secret;
public String username;
public String password;
#OneToMany(mappedBy = "user")
public List<Event> history;
[...Methods...]
}
Any idea why this happens?
My guess is the database you are using does not like you having a table named "user" which is what you get when you don't provide a specific name for your table. I know that Postgres does not allow for a "user" table because "user" is a keyword. I'm not sure for MySQL. Try adding the javax.persistence.Table annotation after your #Entity annotation in the User class:
#Entity
#Table(name = "my_user")
public class User extends Model {
...
}
where you give it a whatever name you want that is not "user". Alternatively (but not tested) you may be able wrap the "user" name in quotes:
#Entity
#Table(name = "\"user\"")
public class User extends Model {
...
}
Be careful with column names.
2012-08-08T12:58:29+00:00 app[web.1]: 12:58:29,513 ERROR ~ Unsuccessful: create table users (id int8 not null, email varchar(255), enabled bool not null, name varchar(255), user varchar(255), primary key (id))
2012-08-08T12:58:29+00:00 app[web.1]: 12:58:29,514 ERROR ~ ERROR: syntax error at or near "user"
That was my case, changing column "user" to "userId" solved my issue