Working non-working Hibernate Derby error - hibernate-mapping

I have this very simple entity with the exact same annotations I use prior to adding it to the project. I get the stacktrace below,shown and also, not shown, when adding the FK constaint. The error occurs whether I use the primitive or object for the index. Everything seems correct, can someone edify me? ty.
#Setter
#Getter
#NoArgsConstructor
#Entity
public class User {
#Id
#GeneratedValue
int user_id;
private String name;
private String email;
private String password;
#ManyToMany
#JoinTable(name = "user_role",joinColumns = #JoinColumn(name = "user_id"),inverseJoinColumns = #JoinColumn(name = "role_id"))
private Set<Role> roles;
}
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error
executing DDL "create table user (user_id integer not null, email
varchar(255), name varchar(255), password varchar(255), primary key
(user_id))" via JDBC Statement at
org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:67)
~[hibernate-core-5.4.17.Final.jar:5.4.17.Final]

I know, I know DTFS, Sorry, for the clutter and lost cycles of attention;)

Related

JPA error in kotlin : Class 'Student' should have [public, protected] no-arg constructor

Does anyone know how I can solve this problem: 'Class 'Student' should have [public, protected] no-arg constructor'?
It's moaning about the relation to SchoolLesson
import javax.persistence.Entity
import javax.persistence.GeneratedValue
import javax.persistence.GenerationType
import javax.persistence.Id
import javax.persistence.JoinColumn
import javax.persistence.ManyToOne
#Entity
data class Student(
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long = -1,
#ManyToOne
#NotNull
#JoinColumn(name = "school_lesson_id", referencedColumnName = "id")
val report: SchoolLesson,
)
#EDIT added SchoolLesson on request
import javax.persistence.*
import javax.validation.constraints.NotNull
#Entity
data class SchoolLesson(
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(nullable = false)
val id: Long = -1,
#NotNull
val name: String = "",
)
Never use data classes for #Entities. It causes a bunch of problems later on. Follow best practices listed here: https://www.jpa-buddy.com/blog/best-practices-and-common-pitfalls/.
You can use the no-arg compiler plugin, which will add "an additional zero-argument constructor". Details are in the link.
Do not use #Data, instead declare all the necessary annotations to generate what you need. In this case:
#Entity
#Getter
#Setter
#RequiredArgsConstructor
#NoArgsConstructor
public class SchoolLesson {
when you do not create any constructor for class A but create objects of class A from other place, that time compiler creates a no argument constructor under the hood & executes without error. On the other hand, when you create a constructor having some parameters explicitly but do not create any no arg constructor explicitly with the hope in mind that constructor will create a one for you that time it will give you compile error. So, when you create constructor having some parameters, then you also need to create a no argument constructor explicitly in your class. Ref Links that might help here
Why do we need a default no argument constructor in Java?
https://www.quora.com/Is-it-possible-to-define-a-parameterized-constructor-for-a-class-without-defining-a-parameter-less-constructor-in-Java
You may provide default value for all data class properties:
#Entity
data class Student(
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long = -1,
#ManyToOne
#NotNull
#JoinColumn(name = "school_lesson_id", referencedColumnName = "id")
val report: SchoolLesson = SchoolLesson()
)

Hibernate inheritance without table for basic entity

I've never used inheritance in hibernate and I don't know which strategy should I use (or even do I really need to use strategy). I have three tables with the same interface (the same columns) and I want to create three entities with basic interface for them so it will look like this:
#Entity
+ Basic
+ #Entity
#Table(name="TABLE_1")
Table1
+ #Entity
#Table(name="TABLE_2")
Table2
+ #Entity
#Table(name="TABLE_3")
Table3
As you see I don't want to use table for basic entity. If it is possible to do this kind of inheritance, how to do it? Maybe I don't need 'hibernate' inheritance and I should use normal inheritance?
In application it is used like this:
Somewhere in configuration we store information which entity to use (Table1, Table12 or Table3)
Choosen entity is used in our queries (some writen in HQL, some in Criteria) so each query should know which entity to use.
EDIT
What's more each entity can be used as attribute of some entities and we wan't to know which table should be used. For example:
#Entity
#Table(name="USER")
class User {
#Id
private Integer id;
#ManyToOne
#JoinColumn(name = "SOME_ID", referencedColumnName = "ID", nullable = false)
private Basic basicEntity; // how to use proper strategy using some configuration value (eg. class static attribute or configuration value stored in db?)
}
I think this is recommended way of achieving your goal:
#MappedSuperclass
public abstract class BaseEntity {
public static final int SHARED_PAREMETER = 2;
#Column(name = "modified", columnDefinition = "TIMESTAMP DEFAULT NOW()")
protected Date modified;
//... other fields, getters and setters
}
#Entity
#Table(name = "TABLE_1")
public class Table1 {
#Id
private Integer id;
#ManyToOne
#JoinColumn(name = "SOME_ID", referencedColumnName = "ID", nullable = false)
private Table2 table2;
}
#Entity
#Table(name = "TABLE_2")
public class Table2 {
#Id
private Integer id;
}
In this case, we will have only two tables but both would have fields from BaseEntity. You can't, though, make a relation in Entity to an abstract class but in processing you're fully entitled to do something like this:
public void process(BaseEntity entity){
// processing..
}

hibernate when merging object sets field to null

I have a class that goes:
#Entity
#Table(name = "TRANSACTIONS")
public class Transaction {
#Id
#Column(name = "TX_ID")
private Long id;
#Basic
#Column(name = "AMOUNT")
private Double amount;
#Column(name = "AMOUNT_COST")
private Double amountCost;
#NotNull
#Column(name = "AMOUNT_TAX")
private Double amountTax;
#NotNull
#Column(name = "BANKACCOUNT")
private String bankAccount;
//getters and setters here
}
the problem is, when I create Transaction object, and fill data, and then I want it to merge, hibernate merges it with fields AMOUNT_COST and BANKACCOUNT set to null. I checked with debugger - the object I want to merge is correctly filled with data, AMOUNT_COST is set to 0.0 and BANKACCOUNT is correct.
I have no clue what might be the problem here:
-I double checked column names
-I double checked my sql table, and types of data
-I tried to put annotations on getters, or on declaration of variable - nothing changes.
When I set columns to 'nullable' then the object is merged with null values, but only for those two fields (!). I'm clueless here, so I really need a hint. Thanks in advance.
ha. I forgot to mention that I'm using extended entity menager, and in this case, it was it's fault.

Play Framework: JPA one-to-many relationship between three entities?

I am building a web application using the play framework and I am running into problems with creating the database model using this schema
**Client** – (many to many) – **Events**
\ /
(one to many) (one to many)
\ /
**COMMENTS**
I am able to create and add the relationships
Event event = new Event("Party");
Client client = new Client("test#gmail.com","fname","lname","street","phonenum");
Comment comment = new Comment("test comment!");
//Add relationships
client.addEvent(event);
event.addClient(client);
event.addComment(comment);
comment.addEvent(event);
event.addClient(client);
client.addComment(comment);
But when I try to persist the data
client.save();
event.save();
comment.save();
I receive the error
[error] Test CommentModelTest.testClientEventCommentRelationship failed:
javax.persistence.PersistenceException: org.h2.jdbc.JdbcSQLException: Unique index or primary
key violation: "PRIMARY_KEY_4A ON PUBLIC.EVENT_CLIENT(EVENT_ID, CLIENT_EMAIL)"; SQL statement:
[error] insert into event_client (client_email, event_id) values (?, ?) [23505-172]
The class definitions are shown below, I would really appreciate it if someone could help me solve this issue. Am I defining the relationship incorrectly? Thanks in advance!
Client Class:
#Entity
public class Client extends Model {
#Id
public String email;
#Required
public String firstName;
#Required
public String lastName;
public String homeAddress;
public String phoneNumber;
#ManyToMany(mappedBy="clients", cascade=CascadeType.ALL)
public List<Event> events = new ArrayList<Event>();
#OneToMany(mappedBy="client", cascade=CascadeType.ALL)
public List<Comment> comments = new ArrayList<Comment>();
Event Class:
#Entity
public class Event extends Model {
#Id
public Long id;
#Required
public String eventName;
#ManyToMany(cascade=CascadeType.ALL)
public List<Client> clients = new ArrayList<Client>();
#OneToMany(mappedBy="event", cascade=CascadeType.ALL)
public List<Comment> comments = new ArrayList<Comment>();
Comment Class:
#Entity
public class Comment extends Model {
#Id
public Long id;
#Required
public String message;
#ManyToOne(cascade=CascadeType.PERSIST)
public Client client;
#ManyToOne(cascade=CascadeType.PERSIST)
public Event event;
---Edit:-------------------------------
I realized where I went wrong. In case you are running into a similar error, check to see if you are using the models correctly! In my JUnit test I tried adding the same client to an event twice, causing the primary key (email) to be duplicated.
the corrected relationship code should be as follows:
client.addEvent(event);
event.addClient(client);
event.addComment(comment);
comment.addEvent(event);
comment.addClient(client);
client.addComment(comment);
The exception says that you are trying to add the same relationship twice.
"PRIMARY_KEY_4A ON PUBLIC.EVENT_CLIENT(EVENT_ID, CLIENT_EMAIL)"
I guess this is on the table between the events and the clients, so it maps the ManyToMany relationship.
client.addEvent(event);
HERE --> event.addClient(client);
event.addComment(comment);
comment.addEvent(event);
HERE --> event.addClient(client);
client.addComment(comment);
It's added twice and there is a unique index that prevents that.

How to fetch data from two tables(one-to-many relations) using Hibernate Createcriteria

How to fetch data from two tables based upon User id ?
*****************Role Class***********************
#Entity
#Table(name = "IUC_CON_USER_ROLE_MAP")
public class Role {
#Id
#Column(name="F_ROLE_MAP_ID")
int rolemap;
#Column(name="F_ROLE_ID")
int roleid;
#OneToMany(mappedBy="role",fetch=FetchType.EAGER)
Set<User> F_USER_ID;
*********************User class*******************
#Entity
#Table(name = "IUC_CON_USER")
public class User implements Serializable {
#Id
#Column(name = "F_USER_ID")
private int id;
#Column(name = "F_USER_NAME")
private String name;
#Column(name = "F_USER_PWD")
private String pwd;
#ManyToOne
#JoinColumn(name="F_USER_ID",insertable=false,updatable=false)
private Role role;
----------setter and getter for properties
}
External edit:
Criteria creation code:
DetachedCriteria uCrit = DetachedCriteria.forClass(User.class, "user");
uCrit.add(Restrictions.eq("user.id", 5));
uCrit.setProjection(Projections.property("user.id"));
DetachedCriteria criteria = DetachedCriteria.forClass(Role.class, "role");
criteria.add(Property.forName("role.F_USER_ID").in(uCrit));
List lt1 = criteria.getExecutableCriteria(getSession()).list();
use createAlias
criteria.createAlias("propertiy_of_main_entity", "aliastName");
For me this fetches entities asociated with root entity via some entity property name;
in your case something like
createAlias("F_USER_ID", "roleUsers");
should do.
Anyway why ins't your field name following commong naming doctrine for Java? WHY_IS_IT_UPPERCASED_WITH_DASHES_LIKE_CONSTANTS_?
All in all everything is explained in Hibernate documentation. If alias won't work, than fetch associations like in examples from Hibernate documentation under link I provided.
You can use below series of statements to fetch User along with the Role:
int userId = 1;
Criteria criteria = session.createCriteria(User.class);
criteria.setFetchMode("role", FetchMode.JOIN);
criteria.add(Restrictions.eq("id", userId));
User user = (User) criteria.uniqueResult();
The default fetching strategy of Hibernate is to fetch the associations lazily, which you need to override at runtime in code, if you want the associations (here the Role) to be fetched along with User. The third statement is doing this overriding by seting the fetch mode to JOIN. This statement FetchMode.JOIN overrides the default behavior, so that Role will be fetched along with the User.