I am new to hibernate and Data JPA. I try to do an insert into my table but the hibernate query has some columns in it that not exist in my table so it will throw an error. Actually at first when I run my code the hibernate add these extra columns to my table and then I change spring.jpa.hibernate.ddl-auto value to none in application.properties, but now when I delete those extra columns from my table and try to insert a new record I see those columns are in insert method.
My Entity classes
#Entity
public class Content {
#Id
#NotNull
#GeneratedValue
Integer id;
//this can be null if it is a question
#Column(name = "content_id")
Integer content_id;
#NotBlank #NotNull
#Column(name = "body")
String body;
#Column(name = "creationDate")
Timestamp creationDate;
#NotNull
#Column(name = "user_id")
Integer user_id;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getContent_id() {
return content_id;
}
public void setContent_id(Integer content_id) {
this.content_id = content_id;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public Timestamp getCreationDate() {
return creationDate;
}
public void setCreationDate(Timestamp creationDate) {
this.creationDate = creationDate;
}
public int getUser_id() {
return user_id;
}
public void setUser_id(Integer user_id) {
this.user_id = user_id;
}
}
my question class extends the content
#Entity
public class Question extends Content {
#NotNull #NotBlank
#Column(name = "subject")
String subject;
#NotNull #NotBlank
#Column(name = "tags")
String tags;
#NotNull
#Column(name = "contentType")
final Integer contentType_id = 1;
#Column(name = "commentCount")
Integer commentCount;
public Question(#Valid #JsonProperty("subject") String subject,
#Valid #JsonProperty("tags") String tags,
#Valid #JsonProperty("body") String body) {
this.subject = subject;
this.tags = tags;
this.body = body;
}
public Integer getContentType_id() {
return contentType_id;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getTags() {
return tags;
}
public void setTags(String tags) {
this.tags = tags;
}
public Integer getCommentCount() {
return commentCount;
}
public void setCommentCount(Integer commentCount) {
this.commentCount = commentCount;
}
}
Service class
#Service
public class QuestionService {
#Autowired
QuestionRepository questionRepository;
public QuestionService(QuestionRepository questionRepository) {
this.questionRepository = questionRepository;
}
public Question postQuestion(Question question){
return questionRepository.save(question);
}
}
Controller
#RequestMapping("easy4lazy/questions")
#RestController
public class QuestionController {
private final QuestionService questionService;
private final int contetnType = 1;
#Autowired
public QuestionController(QuestionService questionService) {
this.questionService = questionService;
}
#PostMapping(path = "/postQuestion" )
public Question postQuestion(#RequestBody Question q){
q.setContent_id(contetnType);
return questionService.postQuestion(q);
}
}
Repository
import com.easy4lazy.proj.model.Question;
import org.springframework.data.repository.CrudRepository;
public interface QuestionRepository extends CrudRepository<Question, Integer> {
}
Error code
Hibernate: insert into content (body, content_id, creation_date, user_id, comment_count, content_type, subject, tags, dtype, id) values (?, ?, ?, ?, ?, ?, ?, ?,'Question', ?)
2019-10-10 18:11:36.513 WARN 11960 --- [nio-8080-exec-3] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1054, SQLState: 42S22
2019-10-10 18:11:36.515 ERROR 11960 --- [nio-8080-exec-3] o.h.engine.jdbc.spi.SqlExceptionHelper : Unknown column 'creation_date' in 'field list'
2019-10-10 18:11:36.520 ERROR 11960 --- [nio-8080-exec-3] o.h.i.ExceptionMapperStandardImpl : HHH000346: Error during managed flush [org.hibernate.exception.SQLGrammarException: could not execute statement]
2019-10-10 18:11:36.547 ERROR 11960 --- [nio-8080-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute statement; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute statement] with root cause
I don't have content_id, creation_date, comment_count and dtype fields in my table and i don't know why hibernate add them into the query.
is there any way to change the query that hibernate created or fix this problem in any other way, how can I control or manage queries create by hibernate???
I also should mention that I use the postman to send data and check my code.
After lots of searching and working, I found that hibernate naming convention for table columns is in a way that it separate words by an underscore and that was the reason that I saw those columns inside the query generated by hibernate. So if you have a variable inside your class like creationDate hibernate try to converted to creation_date so when I change all my column's name in this method problem solved. Also, the dtype column is a special kind of column that will create by hibernate when many classes use the same table to insert data, it is because to distinguish which class insert the record inside the table and hibernate provide its value with the name of that class.
But you do have content_id and creation_date in your Content entity which the Question entity extends from
Related
I am practice Hibernate with the following classes and a MySQL database.
#Entity
#Table(name="Student")
public class Student {
#Id
#GeneratedValue
private int student_id;
private String student_name;
#ManyToOne(cascade=CascadeType.ALL)
private StudentAddress address;
#Transient
#Temporal(TemporalType.DATE)
private Date birthDay;
public Student() {
}
public Date getBirthDay() {
return birthDay;
}
public void setBirthDay(Date birthDay) {
this.birthDay = birthDay;
}
public int getStudent_id() {
return student_id;
}
public void setStudent_id(int rollNo) {
this.student_id = rollNo;
}
public String getStudent_name() {
return student_name;
}
public void setStudent_name(String name) {
this.student_name = name;
}
public StudentAddress getAddress() {
return address;
}
public void setAddress(StudentAddress address) {
this.address = address;
}
}
#Entity
#Table(name="student_address")
public class StudentAddress {
#Id
#GeneratedValue
private int address_id;
private String address_detail;
public int getAddress_id() {
return address_id;
}
public void setAddress_id(int address_id) {
this.address_id = address_id;
}
public String getAddress_detail() {
return address_detail;
}
public void setAddress_detail(String address_detail) {
this.address_detail = address_detail;
}
}
I keep getting the following error message from these sql statements:
Hibernate: insert into student_address (address_detail) values (?)
Hibernate: insert into Student (address_address_id, student_name) values (?, ?)
Error Message:
Unknown column '**address_address_id'** in 'field list'
My database has the field name address_id.
Hibernate keeps appending address to address_id and changes the column name. I could probably change the field name from address to address_address_id in my database but what is causing this to happen. Is it a valid behavior in Hibernate and can I change it?
That's the default column name Hibernate uses for #ManyToOne association:
Default (only applies if a single join column is used): The
concatenation of the following: the name of the referencing
relationship property or field of the referencing entity or embeddable
class; "_"; the name of the referenced primary key column. If there is
no such referencing relationship property or field in the entity, or
if the join is for an element collection, the join column name is
formed as the concatenation of the following: the name of the entity;
"_"; the name of the referenced primary key column.
To specify the desired column name:
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumn(name="address")
private StudentAddress address;
Having this domain class and using hibernate 3.2.6 integrated with JPA under spring 3.2.4
#Entity
public class PriorityDeviceKeyword {
public enum PriorityDeviceKey {
ALL ("ALL", "ALL DEVICES"),
IOS ("IOS", "IOS"),
ANDROID ("ANDROID","ANDROID");
private final String name;
private final String id;
private PriorityDeviceKey(String name, String id) {
this.name = name;
this.id = id;
}
public String getName() {
return name;
}
public String getId() {
return id;
}
}
#Id
private Long id;
#Column(name = "key")
private PriorityDeviceKey key;
#ManyToMany
#JoinTable(name = "t_priority_device_set", joinColumns = #JoinColumn(name = "priority_device__id", referencedColumnName = "id"))
private List<PriorityDevice> priorityDevices;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public PriorityDeviceKey getKey() {
return key;
}
public void setKey(PriorityDeviceKey key) {
this.key = key;
}
public List<PriorityDevice> getPriorityDevices() {
return priorityDevices;
}
public void setPriorityDevices(List<PriorityDevice> priorityDevices) {
this.priorityDevices = priorityDevices;
}
}
When executing this query that I have below method in my DAO class that I execute
#Override
#SuppressWarnings("unchecked")
public Set<PriorityDevices> findPriorityAreas(PriorityDevicesKey key) {
String jpql = "from PriorityDevices as pak where pak.key.name = :keyName";
Query query = entityManager.createQuery(jpql);
query.setParameter("keyName", key.getName());
List<PriorityDevices> priorityDevices = query.getResultList();
return new HashSet<PriorityDevices>(priorityDevices);
}
I get this Exception thrown by the application:
2015-01-14 13:14:50,936 ERROR [com.controller.errors.Error500Controller] - Application thrown an exception
java.lang.IllegalArgumentException: org.hibernate.QueryException: could not resolve property: name of: com.domain.PriorityDevicesKeyword [from com.domain.PriorityDevicesKeyword as
at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:624)
at org.hibernate.ejb.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:96)
at sun.reflect.GeneratedMethodAccessor440.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
Think these changes may work for you:
#Column(name = "key")
#Enumerated(EnumType.STRING)
private PriorityAreaKey key;
and
String jpql = "from PriorityAreaKeyword as pak where pak.key = :keyName";
Query query = entityManager.createQuery(jpql);
query.setParameter("keyName", key);
Hibernate stores enums as an oridnal. Or, when the field is annotated with #Enumerated(EnumType.STRING), as a string with the short name of the Enum. When annotated valid names would be {ALL, IOS, ANDROID}. Either way there is only a single field, the properties of the enum itself are not stored, they are constant after all.
If you want to query for an enum value you have to to query for pak.key = :key and use key as the parameter. Hibernate will do the required translation to ordinal or string.
When I try save instance, I get this strange error:
WARN [15:06:27,917] JDBCExceptionReporter - SQL Error: 20000, SQLState: 42X04
ERROR[15:06:27,917] JDBCExceptionReporter - Column 'ad0b8d24-f596-47cb-9d79-06a3c9c1de26' is either not in any table in the FROM list or appears within a join specification and is outside the scope of the join specification or appears in a HAVING clause and is not in the GROUP BY list. If this is a CREATE or ALTER TABLE statement then 'ad0b8d24-f596-47cb-9d79-06a3c9c1de26' is not a column in the target table.
Row is not inserted into database.
It looks like it is trying to use scenario_id (uuid) as column name. But why?
I am using this Data Access Object:
public interface ScenarioDao extends GenericDao<Scenario, String> {
public List<Scenario> getScenariosWhereOwner(Person owner);
public List<Scenario> getScenariosWhereOwner(Person person, int LIMIT);
...
}
public interface GenericDao <T, PK extends Serializable>{
public PK create(T newInstance) {
PK primaryKey = (PK) getHibernateTemplate().save(newInstance);
return primaryKey;
}
}
POJO:
#Entity
#Table(name = "SCENARIO")
#XmlRootElement
public class Scenario implements Serializable, Comparable<Scenario> {
private static final long serialVersionUID = -6608175331606366993L;
private String scenarioId;
private Person person;
private ResearchGroup researchGroup;
private String title;
private int scenarioLength;
private boolean privateScenario;
private String description;
private String scenarioName;
private String mimetype;
private Set<History> histories = new HashSet<History>(0);
private Set<Experiment> experiments = new HashSet<Experiment>(0);
private boolean userMemberOfGroup;
private Blob scenarioFile;
private String group;
private Boolean availableFile;
private InputStream fileContentStream;
#Transient
public boolean isUserMemberOfGroup() {
return userMemberOfGroup;
}
public void setUserMemberOfGroup(boolean userMemberOfGroup) {
this.userMemberOfGroup = userMemberOfGroup;
}
#Transient
public String getGroup() {
return group;
}
public void setGroup(String group) {
this.group = group;
}
#Transient
public Boolean getAvailableFile() {
return availableFile;
}
public void setAvailableFile(Boolean availableFile) {
this.availableFile = availableFile;
}
public Scenario() {
}
public Scenario(Person person, ResearchGroup researchGroup) {
this.person = person;
this.researchGroup = researchGroup;
}
public Scenario(Person person, ResearchGroup researchGroup, String title,
int scenarioLength, boolean privateScenario, String description,
String scenarioName, String mimetype, Set<History> histories,
Set<Experiment> experiments) {
this.person = person;
this.researchGroup = researchGroup;
this.title = title;
this.scenarioLength = scenarioLength;
this.privateScenario = privateScenario;
this.description = description;
this.scenarioName = scenarioName;
this.mimetype = mimetype;
this.histories = histories;
this.experiments = experiments;
}
#Id
#GeneratedValue(generator = "system-uuid")
#GenericGenerator(name = "system-uuid", strategy = "uuid2")
#Column(name = "SCENARIO_ID", nullable = false, length = 36, scale = 0)
public String getScenarioId() {
return this.scenarioId;
}
public void setScenarioId(String scenarioId) {
this.scenarioId = scenarioId;
}
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "OWNER_ID", nullable = false)
public Person getPerson() {
return this.person;
}
public void setPerson(Person person) {
this.person = person;
}
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "RESEARCH_GROUP_ID", nullable = false)
public ResearchGroup getResearchGroup() {
return this.researchGroup;
}
public void setResearchGroup(ResearchGroup researchGroup) {
this.researchGroup = researchGroup;
}
#Column(name = "TITLE", unique = true)
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
#Column(name = "SCENARIO_LENGTH", precision = 22, scale = 0)
public int getScenarioLength() {
return this.scenarioLength;
}
public void setScenarioLength(int scenarioLength) {
this.scenarioLength = scenarioLength;
}
#Column(name = "PRIVATE", precision = 1, scale = 0)
public boolean isPrivateScenario() {
return this.privateScenario;
}
public void setPrivateScenario(boolean privateScenario) {
this.privateScenario = privateScenario;
}
#Lob
#Type(type = "org.hibernate.type.TextType")
#Column(name = "DESCRIPTION")
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
#Column(name = "SCENARIO_NAME")
public String getScenarioName() {
return this.scenarioName;
}
public void setScenarioName(String scenarioName) {
this.scenarioName = scenarioName;
}
#Column(name = "MIMETYPE")
public String getMimetype() {
return this.mimetype;
}
public void setMimetype(String mimetype) {
this.mimetype = mimetype;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "scenario")
public Set<History> getHistories() {
return this.histories;
}
public void setHistories(Set<History> histories) {
this.histories = histories;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "scenario")
public Set<Experiment> getExperiments() {
return this.experiments;
}
public void setExperiments(Set<Experiment> experiments) {
this.experiments = experiments;
}
#XmlJavaTypeAdapter(BlobSerializer.class)
#Basic(fetch = FetchType.LAZY)
#Lob
#Column(name = "SCENARIO_FILE", nullable = true)
public Blob getScenarioFile() {
return this.scenarioFile;
}
public void setScenarioFile(Blob scenarioFile) {
this.scenarioFile = scenarioFile;
}
#Override
public int compareTo(Scenario scen) {
return this.title.compareTo(scen.getTitle());
}
public void setFileContentStream(InputStream inputStream) {
this.fileContentStream = inputStream;
}
#Transient
public InputStream getFileContentStream() {
return fileContentStream;
}
}
I try to create it using this code:
scenario = new Scenario();
scenario.setPrivateScenario(some boolean);
scenario.setScenarioLength(some int);
scenario.setDescription(some string);
scenario.setTitle(some string);
scenario.setResearchGroup(some ResearchGroup);
scenario.setPerson(some Person);
All these parameters are set correctly. I am also using GenericDao with other objects without errors. Here is insert statement generated by hibernate:
DEBUG[16:07:25,132] SQL - insert into SCENARIO (DESCRIPTION, MIMETYPE, OWNER_ID, PRIVATE, RESEARCH_GROUP_ID, SCENARIO_FILE, SCENARIO_LENGTH, SCENARIO_NAME, TITLE, SCENARIO_ID) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
TRACE[16:07:25,153] BasicBinder - binding parameter [1] as [LONGVARCHAR] - newscenariodescription
TRACE[16:07:25,153] BasicBinder - binding parameter [2] as [VARCHAR] - <null>
TRACE[16:07:25,153] BasicBinder - binding parameter [3] as [VARCHAR] - 9e87924e-3a14-4f82-ad57-c191ead873b5
TRACE[16:07:25,153] BasicBinder - binding parameter [4] as [BIT] - false
TRACE[16:07:25,154] BasicBinder - binding parameter [5] as [VARCHAR] - b399f04f-92a7-427c-9af5-f90055cb1ddc
TRACE[16:07:25,154] BasicBinder - binding parameter [6] as [BLOB] - <null>
TRACE[16:07:25,154] BasicBinder - binding parameter [7] as [INTEGER] - 5
TRACE[16:07:25,154] BasicBinder - binding parameter [8] as [VARCHAR] - <null>
TRACE[16:07:25,154] BasicBinder - binding parameter [9] as [VARCHAR] - newscenario
TRACE[16:07:25,154] BasicBinder - binding parameter [10] as [VARCHAR] - 2d71bcd2-756e-4ffd-82b0-9649d7f05e0b
WARN [16:07:25,180] JDBCExceptionReporter - SQL Error: 20000, SQLState: 38000
ERROR[16:07:25,180] JDBCExceptionReporter - The exception 'java.sql.SQLException: Column '2d71bcd2-756e-4ffd-82b0-9649d7f05e0b' is either not in any table in the FROM list or appears within a join specification and is outside the scope of the join specification or appears in a HAVING clause and is not in the GROUP BY list. If this is a CREATE or ALTER TABLE statement then '2d71bcd2-756e-4ffd-82b0-9649d7f05e0b' is not a column in the target table.' was thrown while evaluating an expression.
When I try execute:
String query = "insert into SCENARIO (DESCRIPTION, MIMETYPE, OWNER_ID, PRIVATE, RESEARCH_GROUP_ID, FILE_CONTENT, SCENARIO_LENGTH, SCENARIO_NAME, TITLE, SCENARIO_ID) values ('newscenariodescription', NULL, '9e87924e-3a14-4f82-ad57-c191ead873b5', 0, 'b399f04f-92a7-427c-9af5-f90055cb1ddc', NULL, 5, NULL, 'text', '2d71bcd2-756e-4ffd-82b0-9649d7f205e0b')";
session.createSQLQuery(query).executeUpdate();
I get same error.
When I try execute query directly I get very strange error:
SQL Error [20000] [38000]: The exception 'java.lang.NoClassDefFoundError: org/jumpmind/symmetric/db/derby/DerbyFunctions' was thrown while evaluating an expression.
SQL Error [XJ001]: Java exception: 'org/jumpmind/symmetric/db/derby/DerbyFunctions: java.lang.NoClassDefFoundError'.
The exception 'java.lang.NoClassDefFoundError: org/jumpmind/symmetric/db/derby/DerbyFunctions' was thrown while evaluating an expression.
The exception 'java.lang.NoClassDefFoundError: org/jumpmind/symmetric/db/derby/DerbyFunctions' was thrown while evaluating an expression.
Java exception: 'org/jumpmind/symmetric/db/derby/DerbyFunctions: java.lang.NoClassDefFoundError'.
org/jumpmind/symmetric/db/derby/DerbyFunctions
I forget to set capture_big_lobs in trigger table. Changing value to 1 solved problem. However if the column is NULL, then SymmetricDS will throw Null Pointer Exception. I am using 3.5.10, so maybe it's solved in newer versions.
I need to use raw SQL within a Spring Data Repository, is this possible? Everything I see around #Query is always entity based.
The #Query annotation allows to execute native queries by setting the nativeQuery flag to true.
Quote from Spring Data JPA reference docs.
Also, see this section on how to do it with a named native query.
YES, You can do this in bellow ways:
1. By CrudRepository (Projection)
Spring Data Repositories usually return the domain model when using query methods. However, sometimes, you may need to alter the view of that model for various reasons.
Suppose your entity is like this :
import javax.persistence.*;
import java.math.BigDecimal;
#Entity
#Table(name = "USER_INFO_TEST")
public class UserInfoTest {
private int id;
private String name;
private String rollNo;
public UserInfoTest() {
}
public UserInfoTest(int id, String name) {
this.id = id;
this.name = name;
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID", nullable = false, precision = 0)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
#Basic
#Column(name = "name", nullable = true)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Basic
#Column(name = "roll_no", nullable = true)
public String getRollNo() {
return rollNo;
}
public void setRollNo(String rollNo) {
this.rollNo = rollNo;
}
}
Now your Projection class is like below. It can those fields that you needed.
public interface IUserProjection {
int getId();
String getName();
String getRollNo();
}
And Your Data Access Object(Dao) is like bellow :
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import java.util.ArrayList;
public interface UserInfoTestDao extends CrudRepository<UserInfoTest,Integer> {
#Query(value = "select id,name,roll_no from USER_INFO_TEST where rollNo = ?1", nativeQuery = true)
ArrayList<IUserProjection> findUserUsingRollNo(String rollNo);
}
Now ArrayList<IUserProjection> findUserUsingRollNo(String rollNo) will give you the list of user.
2. Using EntityManager
Suppose your query is "select id,name from users where roll_no = 1001".
Here query will return an object with id and name column. Your Response class is like bellow:
Your Response class is like this:
public class UserObject{
int id;
String name;
String rollNo;
public UserObject(Object[] columns) {
this.id = (columns[0] != null)?((BigDecimal)columns[0]).intValue():0;
this.name = (String) columns[1];
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRollNo() {
return rollNo;
}
public void setRollNo(String rollNo) {
this.rollNo = rollNo;
}
}
here UserObject constructor will get an Object Array and set data with the object.
public UserObject(Object[] columns) {
this.id = (columns[0] != null)?((BigDecimal)columns[0]).intValue():0;
this.name = (String) columns[1];
}
Your query executing function is like bellow :
public UserObject getUserByRoll(EntityManager entityManager,String rollNo) {
String queryStr = "select id,name from users where roll_no = ?1";
try {
Query query = entityManager.createNativeQuery(queryStr);
query.setParameter(1, rollNo);
return new UserObject((Object[]) query.getSingleResult());
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
Here you have to import bellow packages:
import javax.persistence.Query;
import javax.persistence.EntityManager;
Now your main class, you have to call this function. First get EntityManager and call this getUserByRoll(EntityManager entityManager,String rollNo) function. The calling procedure is given below:
Here is the Imports
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
get EntityManager from this way:
#PersistenceContext
private EntityManager entityManager;
UserObject userObject = getUserByRoll(entityManager,"1001");
Now you have data in this userObject.
Note:
query.getSingleResult() return a object array. You have to maintain the column position and data type with the query column position.
select id,name from users where roll_no = 1001
query return a array and it's [0] --> id and [1] -> name.
More info visit this thread and this Thread
Thanks :)
It is possible to use raw query within a Spring Repository.
#Query(value = "SELECT A.IS_MUTUAL_AID FROM planex AS A
INNER JOIN planex_rel AS B ON A.PLANEX_ID=B.PLANEX_ID
WHERE B.GOOD_ID = :goodId",nativeQuery = true)
Boolean mutualAidFlag(#Param("goodId")Integer goodId);
we can use createNativeQuery("Here Native SQL Query ");
for Example :
Query q = em.createNativeQuery("SELECT a.firstname, a.lastname FROM Author a");
List<Object[]> authors = q.getResultList();
This is how you can use in simple form
#RestController
public class PlaceAPIController {
#Autowired
private EntityManager entityManager;
#RequestMapping(value = "/api/places", method = RequestMethod.GET)
public List<Place> getPlaces() {
List<Place> results = entityManager.createNativeQuery("SELECT * FROM places p limit 10").getResultList();
return results;
}
}
It is also possible to use Spring Data JDBC, which is a fully supported Spring project built on top of Spring Data Commons to access to databases with raw SQL, without using JPA.
It is less powerful than Spring Data JPA, but if you want lightweight solution for simple projects without using a an ORM like Hibernate, that a solution worth to try.
I have following two tables
CREATE TABLE event_type_master (
Event_Type_Code varchar(128) NOT NULL,
PRIMARY KEY (Event_Type_Code)
)
CREATE TABLE event_master (
Event_Code varchar(128) NOT NULL,
Event_Type_Code varchar(128) NOT NULL,
PRIMARY KEY (Event_Code,Event_Type_Code),
CONSTRAINT FK1 FOREIGN KEY (Event_Type_Code) REFERENCES event_type_master (Event_Type_Code)
)
Now I have create model classes for the above relation as follow
EventMaster Class:-
#Entity
#Table(name="event_master")
public class EventMaster implements java.io.Serializable {
private EventMasterId id;
private EventTypeMaster eventTypeMaster;
private String eventName;
public EventMaster() {
}
public EventMaster(EventMasterId id, EventTypeMaster eventTypeMaster) {
this.id = id;
this.eventTypeMaster = eventTypeMaster;
}
public EventMaster(EventMasterId id, EventTypeMaster eventTypeMaster) {
this.id = id;
this.eventTypeMaster = eventTypeMaster;
this.eventName = eventName;
}
#EmbeddedId
#AttributeOverrides( {
#AttributeOverride(name="eventCode", column=#Column(name="Event_Code", nullable=false, length=128) ),
#AttributeOverride(name="eventTypeCode", column=#Column(name="Event_Type_Code", nullable=false, length=128) ) } )
public EventMasterId getId() {
return this.id;
}
public void setId(EventMasterId id) {
this.id = id;
}
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="Event_Type_Code",referencedColumnName = "Event_Type_Code", nullable=false, insertable=false, updatable=false)
public EventTypeMaster getEventTypeMaster()
{
return this.eventTypeMaster;
}
public void setEventTypeMaster(EventTypeMaster eventTypeMaster) {
this.eventTypeMaster = eventTypeMaster;
}
}
EventMasterId Class for Compound Primary Key setting:-
#Embeddable
public class EventMasterId implements java.io.Serializable {
private String eventCode;
private String eventTypeCode;
public EventMasterId() {
}
public EventMasterId(String eventCode, String eventTypeCode)
{
this.eventCode = eventCode;
this.eventTypeCode = eventTypeCode;
}
#Column(name="Event_Code", nullable=false, length=128)
public String getEventCode() {
return this.eventCode;
}
public void setEventCode(String eventCode) {
this.eventCode = eventCode;
}
#Column(name="Event_Type_Code", nullable=false, length=128)
public String getEventTypeCode() {
return this.eventTypeCode;
}
public void setEventTypeCode(String eventTypeCode) {
this.eventTypeCode = eventTypeCode;
}
public boolean equals(Object other) {
........
}
public int hashCode() {
..........
}
}
EventTypeMaster Class
#Entity
#Table(name="event_type_master")
public class EventTypeMaster implements java.io.Serializable {
private String eventTypeCode;
private String eventTypeName;
private Set<EventMaster> eventMasters = new HashSet<EventMaster>(0);
public EventTypeMaster() {
}
public EventTypeMaster(String eventTypeCode) {
this.eventTypeCode = eventTypeCode;
}
public EventTypeMaster(String eventTypeCode, String eventTypeName, Set eventMasters) {
this.eventTypeCode = eventTypeCode;
this.eventTypeName = eventTypeName;
this.eventMasters = eventMasters;
}
#Id
#Column(name="Event_Type_Code", unique=true, nullable=false, length=128)
public String getEventTypeCode() {
return this.eventTypeCode;
}
public void setEventTypeCode(String eventTypeCode) {
this.eventTypeCode = eventTypeCode;
}
#OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="eventTypeMaster")
#JoinColumn(name="Event_Type_Code", referencedColumnName = "Event_Type_Code")
public Set<EventMaster> getEventMasters() {
return this.eventMasters;
}
public void setEventMasters(Set<EventMaster> eventMasters) {
this.eventMasters = eventMasters;
}
}
After setting All I created a HebernateUtil Class using Netbeans to connect to HibernateSession Factory and tried to Test adding a record to event_master table as follow
Session session = null;
session = NewHibernateUtil.getSessionFactory().getCurrentSession();
try {
org.hibernate.Transaction tx = session.beginTransaction();
EventMasterId key1=new EventMasterId();
EventTypeMaster eTypeMaster1=new EventTypeMaster();
eTypeMaster1=(EventTypeMaster)session.load(EventTypeMaster.class, "e1");
key1.setEventCode(eTypeMaster1.getEventTypeCode());
key1.setEventCode("Test_Event_Code");
EventMaster em=new EventMaster();
em.setId(key1);
em.setEventTypeMaster(eTypeMaster1);
em.setEventDesc("Event Description");
session.save(em);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
}
But I am getting following Error
Hibernate: insert into event_master (Create_DTTM, Created_By, Event_Desc, Event_Name, Event_Short_Name, Last_Mod_By, Last_Mod_DTTM, Event_Code, Event_Type_Code) values (?, ?, ?, ?, ?, ?, ?, ?, ?)
1473 [main] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: 1048, SQLState: 23000
1473 [main] ERROR org.hibernate.util.JDBCExceptionReporter - Column 'Event_Type_Code' cannot be null
1474 [main] ERROR org.hibernate.event.def.AbstractFlushingEventListener - Could not synchronize database state with session
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:94)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:167)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1028)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:366)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
at test.NewMain.main(NewMain.java:46)
Caused by: java.sql.BatchUpdateException: Column 'Event_Type_Code' cannot be null
at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1666)
at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1082)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
Please help me to solve this.
I think you have a typo.
key1.setEventCode(eTypeMaster1.getEventTypeCode());
key1.setEventCode("Test_Event_Code");
Should the first line be key1.setEventTypeCode.