I'm looking for a way to set the "default" mapping that Hibernate applies to a variable name in a Java object to query it against the database. At the moment we are using the inline javax.persistence markup to manually set column names, but since we have a rigid naming policy for our database it would be nice to be able to just skip on the manual naming and let Hibernate do the mapping. However, at the moment this doesnt work nice at all with anything save for local, non-primary key fields.
At the moment, Hibernate seems to be set to map non-foreign keys to just their name (see "foo" in the below example class), and foreign-keys to "variableName_ReferencedTable_Id" (see "bar" in the below example class). We would like non-foreign keys to stay as they are, except for the variable marked #id, which we would like to be mapped to "TableName_Id", and we would like foreign keys to be mapped to "variableName_Id". Is this even possible, or do we just have to put up with manual mapping?
package testPackage.test
import javax.persistence.CascadeType;
import javax.persistence.Column;
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
public class Table1 {
private int id;
private int localVariable;
private int foreignKeyVariable;
// Constructor here somewhere
// Without a #Column( name="Table1_Id" ), this comes out as "id".
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
// This works fine, being a local field.
public int getLocalVariable() {
return localVariable;
}
public void setLocalVariable(int LocalVariable) {
this.localVariable = localVariable;
}
// Withou a #JoinColumn( name="foreignKeyVariable_Id" ) , this comes out as "foreignKeyVariable_Table2_Id".
#ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE} )
#JoinColumn() // Not sure if this would even be necessary at all. Happy to leave it out if possible.
public int getForeignKeyVariable() {
return foreignKeyVariable;
}
public void setForeignKeyVariable(int foreignKeyVariable) {
this.foreignKeyVariable = foreignKeyVariable;
}
}
(copied from comment)
Hibernate does have the concept of NamingStrategy, but it's not sensitive to whether than object is a PK or a normal column, so that's not going to be of any use.
Related
I need to create entity based on information from database. Based on database I created string like this :
` package az.com.ds.entity.crudEntity;
import javax.persistence.Table;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Column;
#Table(name = "CMN_SP", schema = "CMN")
#Entity
public class CmnSpEnt {
#Id
private Integer id;
#Column(name = "NAME")
private String name;
} `
Then I created java file based on this string and compiled it at runtime. Everything works perfectly to this step. But when I want to get data based on entity it throws exception as
org.hibernate.hql.internal.ast.QuerySyntaxException: CmnSpEnt is not mapped [Select x from CmnSpEnt x ].
Now I need to map entity for hibernate in order to get data from database. Is there a way to accomplish this?
I'm really stuck here and I need help, I've been trying to run my application and let hibernate create tables using my java entities, but it keeps raising this exception :
Unable to execute schema management to JDBC target [create table answer (id_answer bigint not null auto_increment, order integer, text varchar(255), question_id_question bigint, primary key (id_answer))]
Says that there is an error in my SQL syntax, even though i didn't write any sql, i let hibernate handle it all.
Below are my classes and configuration:
Answer.java :
package com.sfm.elearn.business.entities;
import java.io.Serializable;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import com.fasterxml.jackson.annotation.JsonIgnore;
#Entity
public class Answer implements Serializable {
#Id #GeneratedValue
private Long idAnswer;
private String text;
private Integer order;
#ManyToOne
#JsonIgnore
private Question question;
public Answer() {
super();
// TODO Auto-generated constructor stub
}
public Answer(String text, Integer order, Question question) {
super();
this.text = text;
this.order = order;
this.question = question;
}
public Long getIdAnswer() {
return idAnswer;
}
public void setIdAnswer(Long idAnswer) {
this.idAnswer = idAnswer;
}
}
This is my configuration :
spring.datasource.url=jdbc:mysql://localhost:3306/ElearningBase
spring.datasource.username=root
spring.datasource.password=654321
spring.datasource.testWhileIdle=true
spring.datasource.validationQuery=SELECT 1
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
EDIT: I found the error , the attribute "order" is a reserved SQL keyword that's what was causing the error, changing the variable's name solved it!
If Hibernate is creating your tables for your then your hibernate.ddl-auto property should be set to 'create' or 'create-drop'. The update option means Hibernate expects your tables to already exist. See: Hibernate hbm2ddl.auto possible values and what they do?
Being new to ORM, I'd like to find a way to define a simple (meaning without an additional entity) mapping for a list (or a set) of strings within an entity. I found this sample:
import java.util.Set;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
#Entity
public class Book {
#Id
#GeneratedValue
private Long id;
#ElementCollection
#CollectionTable(name = "tags")
private Set<String> tags;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Set<String> getTags() {
return tags;
}
public void setTags(Set<String> tags) {
this.tags = tags;
}
}
which seems to fit my needs. However, processing this class with Eclipse's hibernate3-maven-plugin:2.2:hbm2ddl, I end up with the following error:
[ERROR] Failed to execute goal
org.codehaus.mojo:hibernate3-maven-plugin:2.2:hbm2ddl (default) on
project test-database: Execution default of goal
org.codehaus.mojo:hibernate3-maven-plugin:2.2:hbm2ddl failed: Could
not determine type for: java.util.Set, at table: Book, for columns:
[org.hibernate.mapping.Column(tags)] -> [Help 1]
Specifying #ElementCollection(targetClass=String.class) did not help. Adding a column definition to the tags field (#Column(name = "tags", columnDefinition="character varying (255)", nullable = false)) leads to a successful build but produces this SQL:
create table Book (
id int8 not null,
tags character varying (255) not null,
primary key (id)
);
which is not what I want, as I was expecting to end up with a tags table linked to the books table. Could someone point me to the right direction ? Thank you.
#ElementCollection has been introduced in JPA v 2.0: the mapping you've done is correct. However make sure the maven hibernate plugin you use is at the correct version. Hibernate itself is compliant with JPA 2.0 starting at version 3.5.
You should create a Tag table : tag_id pk, book_id fk references id from book and any other columns you want
and map you list with something like:
#OneToMany(mappedBy="book",fetch=FetchType.LAZY, cascade=CascadeType.REMOVE)
create your tag class with all your columns from database+ a Book object named book for exemple and map this book with:
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="id",insertable=false,updatable=false)
I want to use Postgresql network data type of mac address (macaddr) in Hibernate ORM. How could I map macaddr type to a entity class property? What is the best way of doing so? I never used non standard SQL types in Hibernate
Thx
Mac address is a String. If it's a #OneToOne relationship between the mac address and its user, then you don't have to make an entity class out of simple strings, just include it as a field on whatever entity needs it, like so:
private String macAddress;
If the same mac address is used by multiple entities and you want to reuse the value (normalize), then you'd make an entity like this:
package com.acme.model;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class MacAddress implements Serializable {
private static final long serialVersionUID = 1l;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String value;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
I just solve a problem like this,so I insert and get row from DB postgresql 9 successfully. The solution explained completely is in this link network postgres types on hibernate
Because of the mac-address is never totaly validated, there is no Standard-Type in Java. You can use
#ColumnTransformer(read="CAST(mac AS varchar)", write="CAST(? AS macaddr)") String
instead to read/write it as String.
I just updated OpenJPA from version 1.2 to 2.2 and many of my JUnits failed. Most of them because ManyToOne relation changed behavior. Lets say we have two entities
package org.my;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.ManyToOne;
#Entity
public class Many {
#ManyToOne(fetch = FetchType.LAZY, optional = false)
private One one;
public One getOne() {
return one;
}
public void setOne(One one) {
this.one = one;
}
}
and
package org.my;
import java.util.List;
#Entity
public class One {
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "one")
private List<Many> many;
public List<Many> getMany() {
return many;
}
public void setMany(List<Many> many) {
this.many = many;
}
}
When I Create One object and set to it List of Many, than persist and commit I got an exception like this
org.apache.openjpa.persistence.InvalidStateException: The field "one" of instance "org.my.Many#4d9cfefb" contained a null value; the metadata for this field specifies that nulls are illegal.
I thought that OpenJPA cat find One object and put it into Many.one field, am I wrong? If not how can I achieve this?
Every Many object in the List of One object should be setOne first before you save it