Mapping java objects using hibernate annotations? - java

I am attempting to map two Java classes using Hibernate. When I compile I get the following error:
Caused by: org.h2.jdbc.JdbcSQLException: Column "COMMENTS0_.DELETED" not found;
Have compared to many examples and everything seems to be correct but there is obviously an error in my mapping. Here is my code:
SQL
-- Table 'TEST_STEP_COMMENT'
CREATE TABLE IF NOT EXISTS `TEST_STEP_COMMENT` (
`id` BIGINT NULL DEFAULT NULL AUTO_INCREMENT,
`test_step_comment` TEXT NOT NULL,
`date` DATETIME NOT NULL,
`test_step_id` BIGINT NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `FK_TEST_STEP_COMMENT_TEST_STEPS`
FOREIGN KEY (`test_step_id`)
REFERENCES `TEST_STEPS` (`id`)
ON DELETE RESTRICT
ON UPDATE RESTRICT);
CREATE INDEX `FK_TEST_STEP_COMMENT_TEST_STEPS_idx` ON `TEST_STEP_COMMENT` (`test_step_id` ASC);
CREATE TABLE IF NOT EXISTS `TEST_STEPS` (
`id` BIGINT NULL DEFAULT NULL AUTO_INCREMENT,
`deleted` BOOLEAN NULL DEFAULT FALSE,
`execute` LONGTEXT NOT NULL,
`sequence_order` INT NOT NULL,
`test_case_id` BIGINT NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `FK_TEST_STEPS_TEST_CASES`
FOREIGN KEY (`test_case_id`)
REFERENCES `TEST_CASES` (`id`)
ON DELETE RESTRICT
ON UPDATE RESTRICT);
CREATE INDEX `FK_TEST_STEPS_TEST_CASES_idx` ON `TEST_STEPS` (`test_case_id` ASC);
JAVA
#Entity
#Audited
#Table(name = "TEST_STEPS")
public class TestStep
extends AuditedEntity
implements Identifiable<Long>, Ordered<Integer>, Comparable<TestStep> {
#Id
#GeneratedValue
private Long id;
#ManyToOne(optional = false)
#JoinColumn(name = "test_case_id")
private TestCase testCase;
#Column(name = "execute", nullable = false)
private String execute;
#OneToMany(mappedBy = "testStep", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
#Filter(name = "deletedEntityFilter")
private Set<VerifyStep> verifications = Sets.newLinkedHashSet();
#Column(name = "sequence_order", nullable = false)
private Integer sequenceOrder = 0;
#OneToMany(mappedBy = "testStep", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private Set<TestStepComment> comments = Sets.newLinkedHashSet();
#Column(name = "result")
private Integer result;
#Column(name = "data")
private String data;
//getters/setters etc
}
#Entity
#Audited
#Table(name = "TEST_STEP_COMMENT")
public class TestStepComment
extends AuditedEntity
implements Identifiable<Long>{
#Id
#GeneratedValue
private Long id;
#ManyToOne(optional = false)
#JoinColumn(name = "test_step_id")
private TestStep testStep;
#Column(name = "test_step_comment")
private String comment;
#Column(name = "date")
private Date date;
#Override
public Long getId() {
return id;
//getters/setters etc
}
If anyone has any suggestions of what may be causing my problem it would be much appreciated because my mapping seems to be correct based on multiple examples that I have looked at. Thanks!

Related

Spring Boot Jpa relationship with part of Embeded Id

I am creating entity relationships in Spring Boot data JPA. Since those tables being legacy I am not able to modify or add columns. Issue is I am getting error if point part of embedded Id.
My entity classes looks like below:
Class Customer {
#EmbededId
private CustomerPk id;
#Column("NAME")
private String name;
#OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL, mappedBy="customerDetails")
private List<Purchase> purchaseDetails;
...
}
#Embeddable
Class CustomerPk {
#Column("CUSTOMER_ID")
private String customerId
#Column("PURCHASE_ID")
private String productId;
#Column("PURCHASE_DATE")
private String date;
}
Purchase Entity looks like below:
Class Purchase {
#EmbededId
private PurchasePK id;
#Column("TRANSACTION_NAME")
private String transactionName;
#ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.ALL)
#JoinColumns({
#JoinColumn(name="CUSTOMER_ID" referencedColumnName="CUSTOMER_ID")
#JoinColumn(name="PURCHASE_ID" referencedColumnName="PURCHASE_ID")
)}
private Customer customerDetails;
...
}
#Embeddable
Class PurchasePK {
#Column("CUSTOMER_ID")
private String customerId
#Column("PURCHASE_ID")
private String productId;
#Column("TRANSACTION_DATE")
private String date;
}
With above structure I am getting org.hibernate.AnnotationException: referencedColumnNames(CUSTOMER_ID, PURCHASE_ID) of Purchase.customerDetails referencing Customer not mapped to a single property.
If I remove date property from CustomerPK, I am able to make the server up. But with current requirement I need date to be part of the CustomerPK class.
I think if I use part of the composite key as Join Columns I am getting this error.
Working version:
#Entity
public class Customer {
#EmbeddedId
private CustomerPk id;
#Column(name = "NAME")
private String name;
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "customerDetails")
private List<Purchase> purchaseDetails;
}
#Embeddable
public class CustomerPk implements Serializable {
#Column(name = "CUSTOMER_ID")
private String customerId;
#Column(name = "PURCHASE_ID")
private String productId;
#Column(name = "PURCHASE_DATE")
private String date;
}
#Entity
public class Purchase {
#EmbeddedId
private PurchasePK id;
#Column(name = "TRANSACTION_NAME")
private String transactionName;
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumns({
#JoinColumn(name = "CUSTOMER_ID", referencedColumnName = "CUSTOMER_ID", insertable = false, updatable = false),
#JoinColumn(name = "PURCHASE_ID", referencedColumnName = "PURCHASE_ID", insertable = false, updatable = false),
#JoinColumn(name = "PURCHASE_DATE", referencedColumnName = "PURCHASE_DATE", insertable = false, updatable = false)
})
private Customer customerDetails;
}
#Embeddable
public class PurchasePK implements Serializable {
#Column(name = "CUSTOMER_ID")
private String customerId;
#Column(name = "PURCHASE_ID")
private String productId;
#Column(name = "TRANSACTION_DATE")
private String date;
}
Conclusion:
The provided information from #Ray was valid, you missed adding the required join columns to represent the full entity relation, regarding your note for the same #Ray point, yes you are right both columns usage is different but also both columns have their own name which it will not override any row value on runtime.
The result of the above tables and representation is as follows:
create table customer
(
customer_id varchar(255) not null,
purchase_date varchar(255) not null,
purchase_id varchar(255) not null,
name varchar(255),
primary key (customer_id, purchase_date, purchase_id)
);
create table purchase
(
customer_id varchar(255) not null,
transaction_date varchar(255) not null,
purchase_id varchar(255) not null,
transaction_name varchar(255),
purchase_date varchar(255),
primary key (customer_id, transaction_date, purchase_id)
);
alter table purchase
add constraint FK6rkrb8rq8x56kai7g5gm32d1y foreign key (customer_id, purchase_date, purchase_id) references customer;

MySQL one-to-many, Java, hibernate

First...sorry for my description...I hope I can be clear.
I want to create a project, where I have cars and drivers. One car can have one driver and one driver can have many cars.
#Entity
#Table(name = "car")
public class Car {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "carid")
private int id;
#Column(name = "car_producator")
private String producator;
#Column(name = "car_model")
private String model;
#Column(name = "car_culoare")
private String culoare;
#Column(name = "car_esteInchiriata")
private boolean esteInchiriata;
#ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DETACH, CascadeType.REFRESH})
#JoinColumn(name="driver_id")
private Driver driver;
private int car_soferID;
[...]
}
#Entity
#Table(name = "driver")
public class Driver {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "driver_id")
private int driver_id;
#Column(name = "driver_name")
private String name;
#Column(name = "driver_license")
private String license;
#Column(name = "driver_phonenr")
private String phoneNr;
#OneToMany(mappedBy = "driver", cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DETACH, CascadeType.REFRESH})
private List<Car> masini;
[...]
}
and this is the mysql syntax, which i don't understand very clear, if i have one to many relationships, do I need a 3rd table where i have id, carID and driverID for that car? sorry for my dummy questions
CREATE DATABASE IF NOT EXISTS `employee_directory`;
USE `employee_directory`;
DROP TABLE IF EXISTS `driver`;
CREATE TABLE `driver` (
`driver_id` int(11) NOT NULL AUTO_INCREMENT,
`driver_name` varchar(45) DEFAULT NULL,
`driver_license` varchar(45) DEFAULT NULL,
`driver_phonenr` varchar(45) DEFAULT NULL,
PRIMARY KEY (`driver_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
INSERT INTO `driver` VALUES
(1,'Tora1ie','Andrews','leslie#mail#com'),
(2,'Tora2','Baumgarten','emma#mail#com'),
(3,'Tora3i','Gupta','avani#mail#com'),
(4,'Tora4','Petrov','yuri#mail#com'),
(5,'Tora5','Vega','juan#mail#com');
create table `car` (
`carid` int unsigned not null auto_increment,
`driver_id` int unsigned not null,
`car_producator` varchar(45) DEFAULT NULL,
`car_mode` varchar(45) DEFAULT NULL,
`car_culoare` varchar(45) DEFAULT NULL,
TINYINT
`car_esteInchiriata` TINYINT(1) DEFAULT NULL,
index car_driver_index(`driver_id`),
foreign key (`driver_id`) references driver(`driver_id`) on delete cascade,
primary key(`carid`)
);
Its completely upto you to decide as both the solution will work.
For the current code it will not create a third table but every row of Car table will have a driver value.
But it would be better if you make #ManyToMany as in future it will be easy for you even if the requirement changes and will have separate table.

Unexpected table created by ddl-auto update

I have spring-boot application with this two JPA entities joined by one-to-many relation.
#Entity
#Table(name = "todos")
public class ToDo {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column
private String description;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "user_id")
private User user;
#Column
private LocalDate targetDate;
public ToDo() {
}
// Constructors, getters, setter, etc.
}
#Entity
#Table(name = "users")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(unique = true, nullable = false)
private String username;
#Column(nullable = false)
private String password;
#OneToMany(
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<ToDo> toDos = new ArrayList<>();
// Constructors, getters, setter, etc.
}
For such kind of relation I expect to have only two tables but Hibernate create three.
Hibernate: create table todos (id bigserial not null, description varchar(255), target_date date, user_id int8, primary key (id))
Hibernate: create table users (id bigserial not null, password varchar(255) not null, username varchar(255) not null, primary key (id))
Hibernate: create table users_to_dos (user_id int8 not null, to_dos_id int8 not null)
The last one look useless. Why it created and could I prevent that? May be something is wrong in code?
Since your toDos list on the user entity does not have a #JoinColumn annotation, hibernate assumes there's an additional mapping table for this and creates it.
Add the #JoinColumn annotation to the field and it will not be created
See more on this guide
#OneToMany(mappedBy="speciality",fetch = FetchType.LAZY)
#JsonIgnore
private Set<DepartmentMaster> departmentSpeciality;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name="SPECALITY_ID")
#JsonIgnore    
private SpecialityMaster speciality;
Try to do the mapping like this I don't think it should create any problem.

#OneToMany #JoinTable usage with three tables

I have been stuck with one scenario in hibernate, i tried looking for such scenario discussion but i couldnt get so raing here for any suggestions or help,
i have three tables category , category_artical, artical.
CREATE TABLE `category` (
`category_id` int(11) NOT NULL AUTO_INCREMENT,
`category_name` varchar(45) NOT NULL,
`category_description` varchar(45) NOT NULL,
PRIMARY KEY (`category_id`)
);
CREATE TABLE `article` (
`article_id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(70) NOT NULL,
`description` varchar(250) NOT NULL,
`keywords` varchar(150) NOT NULL,
`content` text NOT NULL,
PRIMARY KEY (`article_id`)
);
CREATE TABLE `category_article` (
`category_id` int(11) NOT NULL,
`article_id` int(11) NOT NULL,
'category_article_status' varchar(1) NOT NULL.
'category_article_type' varchar(2) NOT NULL,
PRIMARY KEY (`category_id`,`article_id`),
UNIQUE KEY `article_id_UNIQUE` (`article_id`),
KEY `fk_category` (`category_id`),
KEY `fk_article` (`article_id`),
CONSTRAINT `fk_article` FOREIGN KEY (`article_id`) REFERENCES `article` (`article_id`),
CONSTRAINT `fk_category` FOREIGN KEY (`category_id`) REFERENCES `category` (`category_id`)
);
i have entity for category,
#Entity
#Table(name = "CATEGORY")
public class Category {
private long id;
private String name;
#Id
#GeneratedValue
#Column(name = "CATEGORY_ID")
public long getId() {
return id;
}
#OneToMany(cascade = CascadeType.ALL)
#JoinTable(
name = "CATEGORY_ARTICLE",`enter code here`
joinColumns = #JoinColumn(name = "CATEGORY_ID"),
inverseJoinColumns = #JoinColumn(name = "ARTICLE_ID")
)
private Set<Article> articles;
// other getters and setters...
/*For Article entity is */
#Entity
#Table(name = "ARTICLE")
public class Article {
private long id;
private String title;
private String description;
private String keywords;
private String content;
#Id
#GeneratedValue
#Column(name = "ARTICLE_ID")
public long getId() {
return id;
}
// other getters and setters...
For category_article i have no entity as i am using #jointable in category
So everything work fine till i have only two column in category_article which are category_id and article_id. But as soon as i added two more columns i am confused how to inser data in those coulmns(category_article_status and category_article_type) which are not null.
any suggestions on this.
You should create another entity for CATEGORY_ARTICLE like this.
#Entity
#Table(name = "CATEGORY_ARTICLE")
public class CategoryArticle{
#Id
private Long id;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "category_id")
private Category category;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "article_id")
private Article article;
// other columns
private Boolean categoryArticleStatus;
private Long categoryArticleType;
}
and also should change Category and Article. Remove JoinTable from category entity and change it as bellow.
Category
#Entity
#Table(name = "CATEGORY")
public class Category {
//.....
#OneToMany(mappedBy = "category")
private Set<CategoryArticle> categoryArticleSet;
}
Article
#Entity
#Table(name = "ARTICLE")
public class Article {
//.....
#OneToMany(mappedBy = "article")
private Set<CategoryArticle> categoryArticleSet;
}

OneToMany mapping on Embeddable key

I am attempting to build a permission rule for accessing items (stored in table tab) by the users (stored in table users). The availability whether to see something is stored in permissions_tabs table.
The result should be as if the statement is run (for the user with id=2):
SELECT project.tab.tab_id, project.tab.parent, project.tab.name
FROM project.tab
INNER JOIN project.permissions_tabs
ON project.tab.tab_id=project.permissions_tabs.tab_id
WHERE permissions_tabs.user_id=2 AND permissions_tabs.view=true;
I am attempting to do it via the #OneToMany annotation, but it fails - I receive the message:
Deployment failed. The message was: Exception Description: The
#JoinColumns on the annotated element [field allowedTabs] from the
entity class [class
com.jtsmr.scheduler.persistence.entities.UsersEntity] is incomplete.
When the source entity class uses a composite primary key, a
#JoinColumn must be specified for each join column using the
#JoinColumns. Both the name and the referencedColumnName elements must
be specified in each such #JoinColumn.
Before amending the DB and adding the permissions_tab, it all worked. When I added it - I was unable to write the correct #OneToMany annotation, neither I succeeded in finding manual for my case.
If it is not possible, a solution via JPQL will suffice (I was unable to construct a join operation).
Here is my setup:
DB (creation statements for easier understanding):
CREATE TABLE `users` (
`user_id` bigint(20) NOT NULL,
`username` varchar(45) NOT NULL,
`password` varchar(45) NOT NULL,
`name` varchar(45) NOT NULL,
`email` varchar(80) NOT NULL,
PRIMARY KEY (`user_id`),
UNIQUE KEY `user_id_UNIQUE` (`user_id`),
UNIQUE KEY `username_UNIQUE` (`username`)
);
CREATE TABLE `tab` (
`tab_id` bigint(20) NOT NULL AUTO_INCREMENT,
`parent` bigint(20) NOT NULL DEFAULT '0',
`name` varchar(45) NOT NULL,
PRIMARY KEY (`tab_id`)
);
CREATE TABLE `permissions_tabs` (
`user_id` bigint(20) NOT NULL,
`tab_id` bigint(20) NOT NULL,
`to_view` bit(1) DEFAULT b'0',
`to_edit` bit(1) DEFAULT b'0',
PRIMARY KEY (`user_id`,`tab_id`),
KEY `user_id_idx` (`user_id`),
KEY `tab_id_idx` (`tab_id`),
CONSTRAINT `tab_id` FOREIGN KEY (`tab_id`) REFERENCES `tab` (`tab_id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
);
The JPA Mapping is as follows (functions omitted):
Tabs:
#Entity
#Table(name = "tab")
public class TabEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "tab_id", insertable = false, updatable = false)
private Long tabId;
#Column(name = "parent", insertable = false, updatable = false)
private Long parent;
#Column(name = "name", insertable = false, updatable = false)
private String name;
}
Users:
#Entity
#Table(name = "users")
public class UsersEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "user_id")
private Long userId;
#Column(name = "username")
private String username;
#Column(name = "password")
private String password;
#Column(name = "name")
private String name;
#Column(name = "email")
private String email;
#OneToMany
#JoinTable(
name = "permissions_tabs",
joinColumns
= {
#JoinColumn(name = "user_id", referencedColumnName = "user_id")},
inverseJoinColumns
= {
#JoinColumn(name = "tab_id", referencedColumnName = "tab_id")})
private List<PermissionsTabsEntity> allowedTabs;
}
Primary key for the PermissionsTabsEntity class:
#Embeddable
public class PermissionsTabsPK implements Serializable {
#Column(name = "user_id")
private Long userId;
#Column(name = "tab_id")
private Long tabId;
}
And the PermissionsTabsEntity:
#Entity
#Table(name = "permissions_tabs")
public class PermissionsTabsEntity implements Serializable {
#EmbeddedId
private PermissionsTabsPK id;
#Column(name = "to_view")
private boolean toView;
#Column(name = "to_edit")
private boolean toEdit;
}
Thank you in advance!

Categories

Resources