Many-to-many naming column issue - java

I try to create a ManyToMany relation with one extra column (OrderItem.quantity). So I use following entities:
Orders table:
#Entity(name = "EshopOrder")
#Table(name="eshop_order")
public class EshopOrder implements Serializable{
#Id
#Column(name="id_order")
private int idOrder;
#Column(name="date_created")
private Date dateCreated;
#Column(name="total")
private float total;
#ManyToOne
#JoinColumn(name="id_customer")
private Customer customer;
#OneToMany(mappedBy = "product", cascade = CascadeType.ALL, orphanRemoval = true)
private List<OrderItem> items = new ArrayList<OrderItem>();
public EshopOrder() {
}
... getters, etc.
}
"Join table":
#Entity(name = "OrderItem")
#Table(name="order_item")
public class OrderItem {
#EmbeddedId
private OrderItemId id;
#Column(name="quantity")
private Integer quantity;
#ManyToOne(fetch = FetchType.LAZY)
#MapsId("idOrder")
private EshopOrder order;
#ManyToOne(fetch = FetchType.LAZY)
#MapsId("idProduct")
private Product product;
public OrderItem() {
}
public OrderItem(EshopOrder order, Product product, Integer quantity) {
this.order = order;
this.product = product;
this.quantity = quantity;
this.id = new OrderItemId(order.getIdOrder(), product.getIdProduct());
}
... getters, etc.
}
Product(s) which are order items:
#Entity(name="product")
#Table(name="product")
#NaturalIdCache
#Cache(
usage = CacheConcurrencyStrategy.READ_WRITE
)
public class Product implements Serializable{
#Id
#Column(name="id_product")
private int idProduct;
#Column(name="id_category")
private int idCategory;
#OneToOne
#JoinColumn(name="id_category", insertable=false, updatable =false)
private Category category;
#Column(name="name")
private String name;
#Column(name="description")
private String description;
#Column(name="availability")
private int availability;
#OneToMany(
mappedBy = "order",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<OrderItem> orders = new ArrayList<OrderItem>();
#Column(name="price")
private float price;
public Product() {
}
public Product(int idProduct, int idCategory, String name, String description, int availability, float price) {
this.idProduct = idProduct;
this.idCategory = idCategory;
this.name = name;
this.description = description;
this.availability = availability;
this.price = price;
}
...getters, etc
}
And finally, in order to model the quantity column I use this extra class:
#Embeddable
public class OrderItemId implements Serializable{
#Column(name = "id_order")
private int idOrder;
#Column(name = "id_product")
private int idProduct;
public OrderItemId() {
}
public OrderItemId(int idOrder, int idProduct) {
this.idOrder = idOrder;
this.idProduct = idProduct;
}
... getters, etc.
}
SQL scripts to create database:
CREATE TABLE `product`(
`id_product` int (11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`description` varchar(255) DEFAULT NULL,
`availability` int(11) NOT NULL,
`id_category` int(11) NOT NULL,
`price` float(10,2) NOT NULL)
CREATE TABLE `eshop_order`(
`id_order` int (11) NOT NULL auto_increment,
`date_created` date NOT NULL,
`id_customer` int(11) NOT NULL,
`total` float(10,2) NOT NULL)
CREATE TABLE `order_item`(
`id_order` int (11) NOT NULL,
`id_product` int(11) NOT NULL,
`quantity` int(11) DEFAULT NULL)
These are just snippets in order to show the DB background (column names).
When I try to view items of a order it keeps giving me this exception:
java.sql.SQLSyntaxErrorException: Unknown column 'items0_.order_id_order' in 'field list'. This error looks kinda understandable, there really is no column named order_id_order. Which leads me to idea like it forgot to add a dot operator (items0_.order.id_order) which would make totally sense and should work. Do you know what happened? Can you see what is wrong with it?
The thing is during development proces I completely followed this tutorial. But somehow it doesn't work. I even tried to use various naming strategies, but it didn't have any successful result.

Related

sql constraint violation exception

I have an entity Mathematics referenced by MathematicsAnswer. If a perform a post request on Mathematics, I get the exception that field on MathsAnswer cannot be null. But I actually did cascade on the field. Please I need solution this.
java.sql.SQLIntegrityConstraintViolationException: Column 'question_id' cannot be null
sql schema:
CREATE TABLE MATHEMATICS(
id integer not null auto_increment,
year date not null,
question_no int not null,
question varchar(128) default null,
primary key(id)
) engine=InnoDb;
CREATE TABLE MATHS_ANSWER(
id integer not null auto_increment,
date date default null,
question_no int not null,
question_id int not null,
solution varchar(128) default null,
solution_url varchar(128) default null,
primary key(id),
foreign key(question_id) references MATHEMATICS(id) ON DELETE NO ACTION ON UPDATE NO ACTION
) engine = InnoDb;
entity class:
#Entity
#Table(name = "Mathematics")
public class Mathematics {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private Integer id;
#Column(name = "year")
private Date year;
#Column(name = "question_no")
private Integer questionNo;
#Column(name = "question")
private String question;
#OneToOne(mappedBy = "maths", fetch = FetchType.EAGER,cascade = CascadeType.ALL
)
private MathsAnswers answers = new MathsAnswers();//getters & setters
MathsAnswers.java:
#Entity
#Table(name = "Mathematics")
public class Mathematics {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private Integer id;
#Column(name = "year")
private Date year;
#Column(name = "question_no")
private Integer questionNo;
#Column(name = "question")
private String question;
#OneToOne(mappedBy = "maths", fetch = FetchType.EAGER,cascade = CascadeType.ALL
)
private MathsAnswers answers = new MathsAnswers();//getters & setters
jpaRepo:
#RepositoryRestResource(collectionResourceRel = "mathematics", path = "maths")
public interface MathsRepo extends JpaRepository<Mathematics, Integer> {
}
post request:
{
"year":"2004-01-03",
"questionNo":"4",
"question":"How many weeks makes a year?"
}
The table name specified for my MathsAnswer entity was wrong; should've been Mathsanswer instead of Mathematics.

Hibernate database relation annotations

I've been struggling with this for so long now. I have a database with two tables "product" and "categories"
CREATE TABLE `product` (
`idproduct` int NOT NULL AUTO_INCREMENT,
`idcategory` int DEFAULT NULL,
`product_name` varchar(255) DEFAULT NULL,
`product_category` varchar(255) DEFAULT NULL,
`product_description` varchar(255) DEFAULT NULL,
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`idproduct`),
KEY `fkcat` (`idcategory`),
CONSTRAINT `fkcat` FOREIGN KEY (`idcategory`) REFERENCES `categories` (`idcategory`)
) ENGINE=InnoDB AUTO_INCREMENT=149 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
CREATE TABLE `categories` (
`idcategory` int NOT NULL AUTO_INCREMENT,
`category_name` varchar(255) NOT NULL,
`category_description` varchar(255) DEFAULT NULL,
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`idcategory`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
Now I'm trying to get a hibernate join query so I can retrieve let's say
product_name and category_name
One product belongs only to one category (for example, if the product is "black t-shirt", its value for the column "idcategory" would be 2. This is enforced by the foreign key.
The table categories entries can be associated with more than one product (for example, "category_name" = 2 can be associated with many products.
How can this design be implemented in hibernate entities? I've tried this but isn't working...
#Entity
#Table(name = "product")
public class Product implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "idproduct")
private int idproduct;
#Column(name = "idcategory")
private int idcategory;
#Column(name = "product_name")
private String productName;
#Column(name = "product_description")
private String productdescription;
#Column(name = "product_category")
private String productcategory;
#OneToMany(targetEntity = Categories.class, cascade = CascadeType.ALL)
#JoinColumn(name = "idcategory",referencedColumnName="idcategory")
private List<Categories> category;
#Entity
#Table(name = "categories")
public class Categories {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "idcategory")
private int idcategory;
#Column(name = "category_name")
private String category_name;
#Column(name = "category_description")
private String category_description;
and the query is
SELECT p, c FROM Product p INNER JOIN p.category c
this is not correct
#OneToMany(targetEntity = Categories.class, cascade = CascadeType.ALL)
#JoinColumn(name = "idcategory",referencedColumnName="idcategory")
private List<Categories> category;
Product can't have many categories... it is actually the reverse ->
#Entity
#Table(name = "categories")
public class Categories {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "idcategory")
private int idcategory;
#Column(name = "category_name")
private String category_name;
#Column(name = "category_description")
private String category_description;
#OneToMany(cascade = CascadeType.ALL, mappedBy="category")
private List<Product> products;
and Product
#Entity
#Table(name = "product")
public class Product implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "idproduct")
private int idproduct;
#Column(name = "idcategory")
private int idcategory;
#Column(name = "product_name")
private String productName;
#Column(name = "product_description")
private String productdescription;
#Column(name = "product_category")
private String productcategory;
#ManyToOne
private Categories categories;
Suggestion : rename Categories to Category

Need some light on #oneToMany using Map and #MapKeyColumn

This is my sql table structure,
create table TBL_DEPARTMENT_ONE(
ID integer primary key generated always as identity (start with 50, increment by 1),
name varchar(100)
)
create table TBL_EMPLOYEE_THREE(
ID integer primary key generated always as identity (start with 100, increment by 1),
name varchar(100),
dept_ID integer references TBL_DEPARTMENT_ONE
)
Here we i'v done a structure of one to many relation between Employee and Department where many employees can belong to one Department,
Now, here is the JPA mapping code as follows,
For Employee,
#Entity
#Table(name="TBL_EMPLOYEE_THREE")
public class EmployeeEntityThree implements Serializable{
public EmployeeEntityThree(){}
public EmployeeEntityThree(String name,String mobileNo,DepartmentEntityOne dept){
this.empName = name;
this.department = dept;
this.mobileNo = mobileNo;
}
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="ID")
private Integer employeeId;
#Column(name="MOBILE_NO")
private String mobileNo;
#ManyToOne(cascade={CascadeType.PERSIST,
CascadeType.MERGE},
fetch= FetchType.LAZY,targetEntity=DepartmentEntityOne.class)
#JoinColumn(name="DEPT_ID")
private DepartmentEntityOne department;
.....
...
}
the code below is of Department Entity,
#Entity
#Table(name="TBL_DEPARTMENT_ONE")
public class DepartmentEntityOne implements Serializable{
public DepartmentEntityOne(){ }
public DepartmentEntityOne(String name){
this.deptName = name;
}
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="ID")
private Integer deptId;
#Column(name="NAME")
private String deptName;
#OneToMany(cascade= { CascadeType.MERGE,
CascadeType.PERSIST},
fetch= FetchType.LAZY,mappedBy="department")
#MapKeyColumn(name="xxxxx")
private Map<String,EmployeeEntityThree> employees;
...
..
}
This is the code in my main method for testing,
DepartmentEntityOne deptOne = new DepartmentEntityOne("Mechanical Engineering");
Map<String,EmployeeEntityThree> empMap = new HashMap<String,EmployeeEntityThree>();
EmployeeEntityThree[] array = new EmployeeEntityThree[]{
new EmployeeEntityThree("Amar","9000000001",deptOne),
new EmployeeEntityThree("Akbar","9000000002",deptOne),
new EmployeeEntityThree("Anthony","9000000003",deptOne)
};
empMap.put(array[0].getMobileNo(),array[0]);
empMap.put(array[1].getMobileNo(),array[1]);
empMap.put(array[2].getMobileNo(),array[2]);
deptOne.setEmployees(empMap);
em = emf.createEntityManager();
em.persist(deptOne);
The code works fine with all the inserts done successfully
Now my Question is for the Entity Department
where is have used an #MapKeyColumn(name="xxxx"), where "xxxx" is some garbage value,
Here what should be the name = ?
because prior to this it was name = "mobileNo" which is the property in Employee entity.
This worked too.
So what shoud be the actualy vaue for #MapKetColumn(name= ?)
You should refer to the name column of the Employee table.
#MapKeyColumn(name="NAME")
private Map<String,EmployeeEntityThree> employees;

How to implement a complex many to many relationship in JPA?

Here the db schema
CREATE TABLE Products
(
id INT NOT NULL AUTO_INCREMENT,
category_id INT NOT NULL,
description VARCHAR(100),
price DECIMAL(10, 2) NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (category_id) REFERENCES Categories(id)
) ENGINE = INNODB;
CREATE TABLE Orders
(
id INT NOT NULL AUTO_INCREMENT,
customer_id INT NOT NULL,
status VARCHAR(20) NOT NULL,
date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
FOREIGN KEY (customer_id) REFERENCES Customers(id)
) ENGINE = INNODB;
CREATE TABLE OrderDetails
(
product_id INT NOT NULL,
order_id INT NOT NULL,
quantity INT NOT NULL,
subtotal DECIMAL(10, 2) NOT NULL,
PRIMARY KEY (product_id, order_id),
FOREIGN KEY (product_id) REFERENCES Products(id),
FOREIGN KEY (order_id) REFERENCES Orders(id)
) ENGINE = INNODB;
The models
#Embeddable
public class OrderDetailPK
{
private Product product;
private Order order;
public OrderDetailPK() {}
public OrderDetailPK(Product product, Order order)
{
this.product = product;
this.order = order;
}
}
public class OrderDetail {
#EmbeddedId
private OrderDetailPK id;
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumn(name="product_id", insertable=false, updatable=false)
private Product product;
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumn(name="order_id", insertable=false, updatable=false)
private Order order;
private int quantity;
private double subtotal;
public OrderDetail() {}
public OrderDetail(OrderDetailPK id, int quantity, double subtotal)
{
this.product = id.getProduct();
this.order = id.getOrder();
this.quantity = quantity;
this.subtotal = subtotal;
}
// getters, setters
}
public class Product {
#Id
private int id;
private String description;
private double price;
#ManyToOne
#JoinColumn(name="category_id")
private Category category;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "Products")
private List<OrderDetail> orderDetail;
}
public class Order {
#Id
private int id;
#ManyToOne
#JoinColumn(name="customer_id")
private Customer customer;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "Orders")
private List<OrderDetail> orderDetail;
}
And for some reasons I keep getting the error
Concrete type "class models.OrderDetail" with application identity does not declare any primary key fields.
Could anyone point me out where the problem is ? Thanks
When i did this before (as detailed in this question and answer), i made the fields in the embeddable ID primitives (corresponding to the ID fields of the entities referred to), and then used #MapsId in the entity. I believe this is the simplest (and dare i say correct) of meeting all the requirements: that the fields in the entity are relationships, that the fields in the ID class are primitive, that every column is mapped exactly once (the #MapsId fields not really being mappings, but sort of aliases).
Applying that to your case, the ID class looks like:
#Embeddable
public class OrderDetailPK {
private final int productId;
private final int orderId;
public OrderDetailPK(int productId, int orderId) {
this.productId = productId;
this.orderId = orderId;
}
}
And the entity class looks like:
public class OrderDetail {
#EmbeddedId
private OrderDetailPK id;
#ManyToOne(cascade = CascadeType.ALL)
#MapsId("productId")
private Product product;
#ManyToOne(cascade = CascadeType.ALL)
#MapsId("orderId")
private Order order;
private int quantity;
private double subtotal;
public OrderDetail(Product product, Order order, int quantity, double subtotal) {
this.id = new OrderDetailPK(product.getId(), order.getId());
this.product = product;
this.order = order;
this.quantity = quantity;
this.subtotal = subtotal;
}
protected OrderDetail() {}
}
First of all OrderDetailPK has to implement Serializable.
For second please specify which ID's you are going to use, because you has specified columns product_id and order_id as insertable=false, updatable=false (read-only).
So you need to try something like the following:
#EmbeddedId
#AttributeOverrides({
#AttributeOverride(name = "product_id",column = #Column(name = "product_id")),
#AttributeOverride(name = "listingId",column= #Column(name = "order_id"))
})
private OrderDetailPK id;
More information you may find here:
http://docs.oracle.com/javaee/6/api/javax/persistence/EmbeddedId.html
http://docs.oracle.com/javaee/6/api/javax/persistence/AttributeOverride.html
From the EmbeddedId javadoc:
Relationship mappings defined within an embedded id class are not supported.
So you cannot do it this way. I don't think JPA 1 specifies a standard way to implement this (in JPA 2 there is #MapsId but I never tried), but this is what I usually do and most implementations (I think at least Hibernate, EclipseLink and OpenJPA) support it:
Declare your primary key class using primitive types:
#Embeddable
public class OrderDetailPK implements Serializable
{
private int product;
private int order;
public OrderDetailPK() {}
...
}
Annotate your entity with #IdClass and declare the fields using the same name but the desired types:
#Entity
#IdClass(OrderDetailPK.class)
public class OrderDetail {
#Id
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumn(name="product_id", insertable=false, updatable=false)
private Product product;
#Id
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumn(name="order_id", insertable=false, updatable=false)
private Order order;
...
}
(I have always kept the #Id on the fields in the entity but I didn't recheck if they are mandatory)

#ManyToOne mapping doesn't work with joined inheritance

I have the following database structure:
CREATE TABLE `author` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`email` varchar(255) NOT NULL,
`password` varchar(255) NOT NULL,
PRIMARY KEY (`id`));
CREATE TABLE `message` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(500) NOT NULL,
`text` varchar(50000) NOT NULL,
`author_id` int(10) unsigned DEFAULT NULL,
`creation_date` datetime NOT NULL,
`last_update_date` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `author_id_fk` (`author_id`),
CONSTRAINT `message_ibfk_1` FOREIGN KEY (`author_id`) REFERENCES `author` (`id`));
CREATE TABLE `comment` (
`id` int(10) unsigned NOT NULL,
`post_id` int(10) unsigned NOT NULL,
KEY `message_id_fk` (`id`),
KEY `post_id_fk` (`post_id`),
CONSTRAINT `comment_ibfk_1` FOREIGN KEY (`id`) REFERENCES `message` (`id`),
CONSTRAINT `comment_ibfk_2` FOREIGN KEY (`post_id`) REFERENCES `post` (`id`));
CREATE TABLE `post` (
`id` int(10) unsigned NOT NULL,
KEY `message_id_fk` (`id`),
CONSTRAINT `post_ibfk_1` FOREIGN KEY (`id`) REFERENCES `message` (`id`) ON DELETE CASCADE);
And the following mapping with hibernate(3.5.4-Final):
#Entity
#Table(name = "author")
public class Author {
private Long id = 0L;
private String name;
private String email;
private String password;
private Set<Post> posts;
private Set<Comment> comments;
#Id
#Column(name = "id")
#GeneratedValue
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Column(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Column(name = "email")
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#Column(name = "password")
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
#OneToMany(mappedBy = "author")
public Set<Post> getPosts() {
return posts;
}
public void setPosts(Set<Post> posts) {
this.posts = posts;
}
#OneToMany(mappedBy = "author")
public Set<Comment> getComments() {
return comments;
}
public void setComments(Set<Comment> comments) {
this.comments = comments;
}
}
#MappedSuperclass
#Table(name = "message")
#Inheritance(strategy = InheritanceType.JOINED)
public abstract class Message implements Serializable {
private Long id;
private String title;
private String text;
private Author author;
private Date creationDate;
private Date lastUpdateDate;
#Id
#Column(name = "id")
#GeneratedValue
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Column(name = "title")
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
#Column(name = "text")
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
#ManyToOne
#JoinColumn(name = "author_id")
public Author getAuthor() {
return author;
}
public void setAuthor(Author author) {
this.author = author;
}
#Column(name = "creation_date")
public Date getCreationDate() {
return creationDate;
}
public void setCreationDate(Date creationDate) {
this.creationDate = creationDate;
}
#Column(name = "last_update_date")
public Date getLastUpdateDate() {
return lastUpdateDate;
}
public void setLastUpdateDate(Date lastUpdateDate) {
this.lastUpdateDate = lastUpdateDate;
}
}
#Entity
#Table(name = "comment")
#PrimaryKeyJoinColumn(name="id")
public class Comment extends Message {
private static final long serialVersionUID = 1L;
private Post post;
#ManyToOne
#JoinColumn(name = "post_id")
public Post getPost() {
return post;
}
public void setPost(Post post) {
this.post = post;
}
}
#Entity
#Table(name = "post")
#PrimaryKeyJoinColumn(name="id")
public class Post extends Message {
private static final long serialVersionUID = 1L;
private Set<Comment> comments;
#OneToMany(mappedBy = "post")
public Set<Comment> getComments() {
return comments;
}
public void setComments(Set<Comment> comments) {
this.comments = comments;
}
}
The main idea is that Comment and Post are inherited from Message and I would like both of them to have bidirectional relation. But when I run the following code:
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction tx = session.beginTransaction();
Author author = new Author();
author.setName("mike");
author.setPassword("123");
author.setEmail("mike#gmail.com");
Post post = new Post();
post.setAuthor(author);
post.setCreationDate(new Date());
post.setLastUpdateDate(new Date());
post.setText("Text");
post.setTitle("Title");
Long authorId = (Long)session.save(author);
Long postId = (Long)session.save(post);
tx.commit();
I get the following error:
ERROR JDBCExceptionReporter:101 - Unknown column 'author_id' in 'field list'
Exception in thread "main" org.hibernate.exception.SQLGrammarException: could not insert: [org.blogsample.mappingbeans.Post]
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:92)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:64)
Update
As #JB Nizet mentioned before I changed #MappedSuperclass to #Entity, after that I've got another error mappedBy reference an unknown target entity property: org.blogsample.mappingbeans.Comment.author, this was solved by changing db structure(removed author_id from message table, added it to each of comment, post and created foreign keys for this column) and moving author(and getter/setter with mapping) to Comment, Post classes.
Your Message class shouldn't be annotated with #MappedSuperclass, but with #Entity. #MappedSuperclass means that entities extending this class inherit columns and associations from the super class, but these columns and associations go in the table of the subclass. author_id is not in the comment table or in the post table. It's in the message table.
Moreover #Table can only be used with an entity. Not with a mapped superclass, which is only used to inherit fields and associations, but is not mapped to its own table like an entity is.
I think your issue here is exactly the same as the one highlighted in this question.
Have a look at my answer there to see if that helps.

Categories