store objects from a third party library in a hibernate database - java

Before I start, I don't have much experience with hibernate. I'm working on an application where I use my colleagues library to display some data. There are recording objects I want to store in my database, so I don't need to create them every time I use a particular function. I would like to read them from the database. First I tried to do it like this:
#Entity
public class RecordingEntity
{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Lob
#Column(name = "recording")
private Recording recording;
#ManyToOne
#Column(name = "user")
private User user;
public RecordingEntity(Recording recording, User user)
{
this.recording = recording;
this.user = user;
}
public Recording getRecording()
{
return recording;
}
public Long getId()
{
return id;
}
public void setRecording(Recording recording)
{
this.recording = recording;
}
public void setId(Long id)
{
this.id = id;
}
public Long getUser()
{
return user;
}
public void setUser(User user)
{
this.user = user;
}
}
public class ImportRecording()
{
...
try
{
TapestryDBConnection.performAtomic(new DBAtomicRunnable()
{
#Override
public void run(Session session) throws InterruptedException, IOException, SerialException, SQLException
{
...
RecordingEntity recordingEntity = new RecordingEntity(recording);
session.saveOrUpdate(recordingEntity);
...
}
}, true);
}
return null;
}
This would lead to: java.lang.ClassCastException: Recording cannot be cast to java.sql.Blob
Then I tried it without the #Lob and I got:
org.hibernate.MappingException: Could not determine type for: Recording, at table: RecordingEntity, for columns: [org.hibernate.mapping.Column(recording)]
EDIT:
I have tried to save the object with converting them into byte[] and storing the byte[] on to the database. Unfortunately it is not possible unless the recording class implements the interface Serializable. I would prefer to solve this problem without implementing Serializable.

Related

JPA createQuery where condition does not work

I am trying to use JPA to fetch records from database. However I am able to insert records indatabse and even get all the records using createQuery method of class EntityManager.
But in below case I am not getting why the condition in where clause is not working.
Please help me figure it out.
POJO class :
#Entity
#Table(name = "frameworks_filter")
public class FilteredFrameworksDbStructure {
#Id
#Column(name="id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column(name = "regular_name")
private String regularName;
#Column(name = "component_name")
private String componentName;
#Column(name = "component_owner")
private String componentOwner;
#Column(name = "frameworks")
private String frameworks;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getRegularName() {
return regularName;
}
public void setRegularName(String regularName) {
this.regularName = regularName;
}
public String getComponentName() {
return componentName;
}
public void setComponentName(String componentName) {
this.componentName = componentName;
}
public String getComponentOwner() {
return componentOwner;
}
public void setComponentOwner(String componentOwner) {
this.componentOwner = componentOwner;
}
public String getFrameworks() {
return frameworks;
}
public void setFrameworks(String frameworks) {
this.frameworks = frameworks;
}
}
DAO class method:
public List<FilteredFrameworksDbStructure> getFilteredFrameworks(String regularName) {
EntityManager entityManager = entityManagerFactory.createEntityManager();
List<FilteredFrameworksDbStructure> filteredFrameworksDbStructureList = entityManager
.createQuery("from FilteredFrameworksDbStructure F where F.regularName = :regular", FilteredFrameworksDbStructure.class)
.setParameter("regular", regularName)
.getResultList();
return filteredFrameworksDbStructureList;
}
Issue : Condition in where clause does not work. It simply fetch all the records irrespective of the regularName provided.
Regards,
Parag Vinchurkar
Why don't you use the JpaRepository or CrudRepository to fetch your results? Check out this tutorial here and here on how to use them.
And you can use your where clause. Please see below the example repository you can use to obtain the same results as the entityManager
public interface FilteredFrameworksDbStructureRepo extends JpaRepository<FilteredFrameworksDbStructure , Integer>{
List<FilteredFrameworksDbStructure> findAllByRegularName(String regularName)
}
Please note that you will have to change your id member variable from int to Integer

Hibernate with mysql overwrites pk

Well, I'm using Hibernate for the first time and, unexpectedly, it works. Except for one thing: an insert with a pk already inserted overwrite the record instaed of preventing it.
That's my simple code:
#Controller
public class SimpleController {
#Autowired
UserRepository userRepository;
#GetMapping("/mainPage")
public String viewMainPage(){
return "mainPage";
}
#GetMapping("/nuovo-utente")
public String viewInserisciUtente(Model model){
model.addAttribute("nuovoUtente", new Utente());
return "nuovo-utente";
}
#PostMapping("/nuovo-utente")
public String memorizzaUtente(#ModelAttribute Utente utente){
userRepository.save(utente);
return "output";
}
}
#Entity
public class Utente {
#Id
private int id;
private String citta=null;
private String genere=null;
private String data_nascita=null;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCitta() {
return citta;
}
public void setCitta(String citta) {
this.citta = citta;
}
public String getGenere() {
return genere;
}
public void setGenere(String genere) {
this.genere = genere;
}
public String getData_nascita() {
return data_nascita;
}
public void setData_nascita(String data_nascita) {
this.data_nascita = data_nascita;
}
}
Any help will be appreciated.
EDIT: I've added the entity class to help you understanding my problem. Hoping that this will help.
Thanks you all
If you look at CrudRepository documentation, then we don't have update method, but we only have save method, which is used to add or update existing records.
In your case, you might have updated an entity (except its Id field) and tried saving the entity. So, CrudRepository will update the existing value for given Id, since it is already present.
Try adding ID generation strategy to id field.
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;

stackoverflow creating objects

when I create GET response, I have Stackoveflow error
Controller for answer
#Controller
public class TaskViewController {
#Autowired
private TaskService taskService;
#RequestMapping(value = "/task/view", method = RequestMethod.GET)
public #ResponseBody
AjaxResponseBody getTask(#RequestParam String text) {
int id;
AjaxResponseBody result = new AjaxResponseBody();
Task task;
System.out.println(text);
try {
id = Integer.parseInt(text);
}
catch (Exception e) {
result.setMsg("Invalid task number");
return result;
}
task = taskService.findById(id);
if (task == null){
result.setMsg("Task not found");
return result;
}
result.setTask(task);
return result;
}
}
He uses class AjaxResponseBody for answer
public class AjaxResponseBody {
private String msg;
private Task task;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Task getTask() {
return task;
}
public void setTask(Task task) {
this.task = task;
}
}
and when this controller works I catch
2017-11-24 10:47:10.514 WARN 1448 --- [nio-8080-exec-4] .w.s.m.s.DefaultHandlerExceptionResolver : Failed to write HTTP message: org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: Infinite recursion (StackOverflowError) (through reference chain: tracker.models.Project_$$_jvstd06_4["user"]->tracker.models.User_$$_jvstd06_5["watched_project"]->tracker.models.Project_$$_jvstd06_4["user"]->tracker.models.User_$$_jvstd06_5["watched_project"]->tracker.models.Project_$$_jvstd06_4["user"]->tracker.models.User_$$_jvstd06_5["watched_project"]->tracker.models.Project_$$_jvstd06_4["user"]->tracker.models.User_$$_jvstd06_5["watched_project"]->
How I understand this happens because model User and model Project has links to each other. Model User has an optional field "watched_project".
#Entity
#Table(name = "users")
public class User {
#ManyToOne(fetch = FetchType.LAZY)
private Project watched_project;
public Project getWatched_project() {
return watched_project;
}
public void setWatched_project(Project watched_project) {
this.watched_project = watched_project;
}
And model Project has field with not empry field "author":
#Entity
#Table(name = "projects")
public class Project {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private int id;
#Column(nullable = false)
#NotEmpty(message = "*Please provide project name")
private String projectName;
#ManyToOne(optional = false, fetch = FetchType.EAGER)
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
How I can abort itteration? Or any way?
JSON serialization tries to serialize object and you have circular reference. There are plenty questions in SO about it. If you are using Jackson then you can use annotation #JsonIgnore for Project object inside User or User object inside Project.
Also you can use #JsonManagedReference and #JsonBackReference like in this answer.

Getting Next value from sequence with spring hibernate

I am using spring jpa repository with hibernate to save entites to my oracle database. How I can get the next value of my oracle database sequence using Spring-Hibernate?
This is my Event class :
#Entity
public class Event {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private Long seriesId;
private String description;
public Event() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getSeriesId() {
return seriesId;
}
public void setSeriesId(Long seriesId) {
this.seriesId = seriesId;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
I need to get the next value of the sequence once for the all event series in the event resolver.
public class EventResolver {
#Autowired
private EventRepository eventRepository;
public void createSeriesOfEvents(List<EventAPI> eventsToCreate){
Long seriesId = null; // TODO: Get the series id from database sequence
for (EventAPI currEvent : eventsToCreate){
Event newEvent = new Event();
newEvent.setDescription(currEvent.description);
newEvent.setSeriesId(seriesId);
eventRepository.save(newEvent);
}
}
}
Thanks for any kind of help..
Finally I Solved my problem in the Spring way, All you need is to add a native query in the JpaRepository like this:
public interface EventRepository extends JpaRepository<Event, Long> {
#Query(value = "SELECT seq_name.nextval FROM dual", nativeQuery =
true)
Long getNextSeriesId();
With Spring 5, you can use one of their built-in classes for this task like OracleSequenceMaxValueIncrementer
See all the available options in this package: https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jdbc/support/incrementer/package-summary.html
Annotate your id property like so:
#Id
#GeneratedValue(generator = "idSequence")
#SequenceGenerator(schema = "MYORASCHEMA", name = "idSequence", sequenceName = "MY_ORACLE_SEQ_NAME", allocationSize = 1)
#Column(name="ID")
private Long id;
You can use this approach in JPA:
Query q = em.createNativeQuery("select seq_name.nextval from dual");
return (Long)q.getSingleResult();

Relationships question in hibernate

I'm learning Hibernate and Play framework (also add Java into account...). I'm having problems saving this kind of entity
#Entity
#Table(name="users")
public class User extends Model {
#Required
public String username;
#Column(name="user_displayname",nullable=true)
public String displayname;
#Password
public String user_password;
#Email
#Column(name="user_email",nullable=false,unique=true)
public String user_email;
public String user_salt;
public Date user_joindate;
#ManyToOne
#JoinTable(name="users_meta")
public UserMeta userdata;
#Required
public boolean user_isActive;
#OneToOne(targetEntity=UserPhotos.class,cascade=CascadeType.ALL)
#JoinColumn(name="id",referencedColumnName="userID")
public UserPhotos userPhoto;
#ManyToMany(cascade=CascadeType.ALL)
#JoinTable(name="links_rol2user")
public List<Rol> rol;
public User (String username, models.Pass password, String user_email) {
this.username = username;
this.user_password = password.getHashedPassword();
this.user_salt = password.getUserHash();
this.user_email = user_email;
this.user_joindate = new Date();
this.user_isActive = false;
}
This is my code when I'm registering a user
// check if the validation has errors
if(validation.hasErrors()) {
params.flash(); // add http parameters to the flash scope
validation.keep(); // keep the errors for the next request
register();
} else {
Cache.delete(uuid);
Pass pass = new Pass(password,new Date().toString());
User newUser = new User(firstName, pass, email);
UserMeta utest = new UserMeta(newUser.id);
utest.setUserTownID(pueblos);
newUser.setUserMeta(utest);
newUser.save();
Logger.info("NewUser ID : %s", newUser.getId());
// UserMeta userInfo = new UserMeta(newUser.getId());
// userInfo.setUserTownID(pueblos);
// userInfo.save();
// TODO salvar foto a null
// Confirmation left
Cache.set("thankyou", "alright!", "3mn");
thankyou();
}
I'm trying to save the userMeta, it does creates a new record when I set the userMeta object into newUser (not visible right now), but it doesn't insert the new ID created in newUser.
What kind of relation do I need? before I tweaked the code as it is now, it was a OneToOne relationship, worked quite well, but now when I was completing the register functions it kinda hit me that I needed to save userMeta object too..
If you need more info let me know, I don't know if I explained it well or not, just trying to get the hang of how Hibernate do relations, etc.
Adding UserMeta:
*/
#Entity
#Table(name="users_meta")
public class UserMeta extends Model {
#Lob
#Column(name="userBio")
public String userBio;
#Column(name="userPhotoID",nullable=true)
public Long userPhotoID = null;
#Column(name="userRoleID", nullable=false)
public Long userRoleID = 2L;
#Lob
public String userDescription;
#Column(name="userViews", nullable=false)
public Long userViews = 0L;
#Column(name="userFavoriteCount", nullable=false)
public Long userFavoriteCount = 0L;
#Column(name="userTotalComments", nullable=false)
public Long userTotalComments = 0L;
#Column(name="userTotalUploadedVideos", nullable=false)
public Long userTotalUploadedVideos = 0L;
public Long userTownID;
public Long userID;
public UserMeta() {}
public UserMeta(Long userid) {
this.userBio = "El usuario no ha escrito nada todavia!";
this.userDescription = "El usuario todavia no se ha describido!";
this.userID = userid;
}
public Long getUserTownID() {
return userTownID;
}
public void setUserTownID(Long userTownID) {
this.userTownID = userTownID;
}
}
// pass model
public class Pass {
protected String hashed;
protected String userHash;
public Pass(String passwordToHash, String salt) {
StringBuffer passSalt = new StringBuffer(passwordToHash);
this.userHash = DigestUtils.md5Hex(salt);
passSalt.append(this.userHash);
passSalt.append(Play.configuration.getProperty("application.passwordSalt"));
this.hashed = DigestUtils.sha512Hex(passSalt.toString());
}
public String getHashedPassword() {
return this.hashed;
}
public String getUserHash() {
return this.userHash;
}
}
There seems to be a lot going on there! But from what I can tell, you problem is with the id that you are passing into the UserMeta.
As you are extending Model, the id is being generated by the Model class. However, this is not set until after the entity is saved to the database (as the id is auto-generated by the database).
Therefore, because you are passing the id into the UserMeta before the User object is saved, the value of id will be null.
If you can save the User object before you create your UserMeta object, your code should work.

Categories

Resources