I have created simple spring boot application in Intellij.
I have created Entity Class in that when i write #Id, #Column annotations it is giving error saying annotations not allowed here.
i tried so many different post from stack overflow but my problem not got resolved.
can someone please help on this.
package com.ajinkya.h2demo;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "ROOM")
public class Room {
#Id
#Column(name = "ROOM_ID")
}
The error appears, because you haven't added any field below the annotations. After you add the field, the error will disappear.
#Id
#Column(name = "ROOM_ID")
private int roomId;
If you go to Column.java in java.persistencepackage you will find this declaration
...
* #since 1.0
*/
#Target({METHOD, FIELD})
#Retention(RUNTIME)
public #interface Column {
...
}
This indicated that #Column annotation can only be applied to methods and fields.
Hence in your entity class you would apply it to method or field like below
#Column(name = "is_active")
protected boolean active = true;
or
#Column(name = "is_active")
public boolean isActive() {
return active;
}
Related
I have a Spring Boot User class which always comes up with the error "java.sql.SQLException: Field 'id' doesn't have a default value". I have tried many times to provide a default value, both in the Java class and in the database table, but to no avail. And I have also switched from generation type = auto and = identity, but to no avail. Thank you very much for your help. Here is my Java Class and my Database Table:
package com.ykirby.myfbapp;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.springframework.beans.factory.annotation.Value;
import java.sql.Timestamp;
import java.util.Date;
#Entity // This tells Hibernate to make a table out of this class
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
#Value("#{User.id ?: 0}")
private int id = 12345;
#Column(name = "fbuserid")
private String fbuserid;
#Column(name = "apttime")
#Temporal(TemporalType.TIMESTAMP)
private Date apttime;
#Column(name = "apttitle")
private String apttitle;
#Column(name = "aptaddress")
private String aptaddress;
#Column(name = "aptlonglat")
private String aptlonglat;
#Column(name = "aptdetails")
private String aptdetails;
public String getFbuserid() {
return fbuserid;
}
public void setFbuserid(String fbuserid) {
this.fbuserid = fbuserid;
}
public Date getApttime() {
return apttime;
}
public void setApttime(Date apttime) {
this.apttime = apttime;
}
public String getApttitle() {
return apttitle;
}
public void setApttitle(String apttitle) {
this.apttitle = apttitle;
}
public String getAptaddress() {
return aptaddress;
}
public void setAptaddress(String aptaddress) {
this.aptaddress = aptaddress;
}
public String getAptlonglat() {
return aptlonglat;
}
public void setAptlonglat(String aptlonglat) {
this.aptlonglat = aptlonglat;
}
public String getAptdetails() {
return aptdetails;
}
public void setAptdetails(String aptdetails) {
this.aptdetails = aptdetails;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
The changes in your User entity class may sometimes not reflect your DB schema accurately. You can try one of these below solutions:
1. Update your DB schema manually by adding AUTO_INCREMENT attribute
ALTER TABLE `user` CHANGE COLUMN `id` `id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT;
2. Drop the User table in your DB, and rerun the application
Make sure that spring.jpa.hibernate.ddl-auto is set to create or update. The default is none if you are NOT using an embedded/in-memory DBs like H2 database.
This configuration of Spring Data JPA will set Hibernate's hibernate.hbm2ddl.auto to the setting value. In our case, it is create or update.
You can read more about this in the below articles and docs.
Spring Boot reference - Database Initialization
What are the possible values of the Hibernate hbm2ddl.auto configuration and what do they do
In production, I suggest you not to use this option but instead use a database migration tool like Liquibase or Flyway and leave the spring.jpa.hibernate.ddl-auto configuration to be none.
More reads about this Hibernate: hbm2ddl.auto=update in production?
You should drop the existing database and re-generate it because sometimes changes done through the model don't reflect properly in the database. While re-generating the database you can scaffolding it with SchemaExport.
Does
#Column(name = "apttitle")
private String apttitle="default";
work?
I'm a beginner with spring and I have this little issue. "No property questionId found for type CourseTestCompleteField!" I have 2 model classes that are connected via a one to one join.
That 2 model class are:
package com.example.springboot.models;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
#Entity
#Table(name = "questions")
public class CourseTestQuestion {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="question_id")
private Long id;
#NotBlank
#Column(name = "question_course")
private String questionCourse;
#NotBlank
#Column(name = "question_type")
private String questionType;
public CourseTestQuestion(){
}
public CourseTestQuestion(String questionCourse, String questionType) {
this.questionCourse = questionCourse;
this.questionType = questionType;
}
// public getters and setters for all fields here
}
And:
package com.example.springboot.models;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
#Entity
#Table(name = "quiz_complete_field_questions",
uniqueConstraints = {
#UniqueConstraint(columnNames = "question_id")
}
)
public class CourseTestCompleteField {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotBlank
#Column(name = "question_content")
private String questionContent;
#NotBlank
#Column(name = "answer")
private String answer;
#NotBlank
#Column(name = "points")
private String points;
#NotBlank
#Column(name = "course")
private String course;
#NotBlank
#Column(name = "teacher_username")
private String teacher;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "question_id", referencedColumnName = "question_id")
private CourseTestQuestion courseTestQuestion;
public CourseTestCompleteField(){
}
public CourseTestCompleteField(CourseTestQuestion courseTestQuestion, String question, String answer, String points, String course, String teacher) {
this.courseTestQuestion = courseTestQuestion;
this.questionContent = question;
this.answer = answer;
this.points = points;
this.course = course;
this.teacher = teacher;
}
// public getters and setters for all fields here
}
My repo for both:
package com.example.springboot.repository;
import com.example.springboot.models.Course;
import com.example.springboot.models.CourseTestQuestion;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
#Repository
public interface CourseTestQuestionRepository extends JpaRepository<CourseTestQuestion, Long> {
Optional<CourseTestQuestion> findById(Long id);
Optional<CourseTestQuestion> findByQuestionCourse(String questionCourse);
}
And:
package com.example.springboot.repository;
import com.example.springboot.models.CourseTestCompleteField;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
#Repository
public interface CourseTestCompleteFieldRepository extends JpaRepository<CourseTestCompleteField, Long> {
Optional<CourseTestCompleteField> findById(Long id);
Optional<CourseTestCompleteField> findByQuestionId(Long questionId);
Optional<CourseTestCompleteField> findByCourse(String course);
List<CourseTestCompleteField> findByQuestionContent(String questionContent);
List<CourseTestCompleteField> findByTeacher(String teacher);
Boolean existsByQuestionContent(String questionContent);
}
The problem is with Optional<CourseTestCompleteField> findByQuestionId(Long questionId);but I don't get it why, because in database I have the table for CourseTestCompleteFieldModel with question_id column, and in CourseTestCompleteField I have CourseTestQuestion object. Tho, the table for CourseTestCompleteField has a different name, could be this a problem? I should rename the table to course_test_complete_field?
Can someone help me please? Thank you
Since,This is a query on nested Object. You need to update your query as this.
Optional<CourseTestCompleteField> findByCourseTestQuestion_Id(Long questionId);
This works even without "_"
Optional<CourseTestCompleteField> findByCourseTestQuestionId(Long questionId);
But better to put "_" while accessing nested fields for better readability.
There is no field call questionId in you entity and you have id only.
That's you got error. You can use that findyById(). That's only enough.
If you would like write JPA repository method like findBy..., getBy..., deleteBy...., countBy..., After this you need append exact field name from entity.
For example if you entity have name then can write below methods. findByName(); deleteByName(); countByName();
So try as below.
findBycourseTestQuestion(Object o);
Pass questions object.
I have a DTO as below:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import reactor.core.publisher.Flux;
#Data
#NoArgsConstructor
#AllArgsConstructor
public class InternetPackageDto {
private String id;
private String name;
private String termsAndConditions;
private String price;
private Flux<String> packageAttributes;
private Flux<String> extras;
}
And a Database Object as below:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import reactor.core.publisher.Flux;
#Document("internet_packages")
#Data
#NoArgsConstructor
#AllArgsConstructor
public class InternetPackage {
#Id
private String id;
private String name;
private String termsAndConditions;
private String price;
private Flux<StoreableAttribute> attributes;
private Flux<StoreableAttribute> extras;
}
The StorableAttribute Database Model like so:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
#Document("package_attributes")
#Data
#NoArgsConstructor
#AllArgsConstructor
public class StoreableAttribute {
#Id
private String id;
private String name;
private String description;
}
On the Data Object the fields: Flux<StoreableAttribute> attributes and Flux<StoreableAttribute> extras are stored in a separate collection alongside the Package Object. And is handled by the mapper as below:
public InternetPackage fromDto(InternetPackageDto dto) {
var internetPackage = new InternetPackage();
internetPackage.setName(dto.getName());
internetPackage.setPrice(dto.getPrice());
internetPackage.setId(dto.getId());
internetPackage.setExtras(this.resolePackageExtras(dto));
internetPackage.setAttributes(this.resolePackageAttributes(dto));
return internetPackage;
}
private Flux<StoreableAttribute> resolePackageExtras(InternetPackageDto dto) {
return this.storeableAttributeService.resolveAttributes(dto.getExtras());
}
for the extra and similarly for the attributes also.
And a simple controller method as below:
#PostMapping(produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
public Mono<InternetPackageDto> update(#RequestBody InternetPackageDto incomingPackageDto) {
return this.packageService
.updatePackage(this.dtoMapper.fromDto(incomingPackageDto))
.map(this.dtoMapper::toDto);
}
And when I make a post request I get an error stating
org.springframework.core.codec.CodecException: Type definition error: [simple type, class reactor.core.publisher.Flux]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `reactor.core.publisher.Flux` (no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
at [Source: (io.netty.buffer.ByteBufInputStream); line: 2, column: 13] (through reference chain: com.example.api.dto.InternetPackageDto["extras"])
Some more information:
I am using the class InternetPackageDto as a request object as well as a response object.
I am using Flux<String> and not List<String> since I wasn't sure if doing blocking resolution to list was a good idea.
The attributes are stored and managed separately.
And during the time of updating or inserting the package those; if a new extra or attribute is included the attributes collection in db will be updated with the insertion of new incoming extras and attributes.
It seems like I might have made a stupid mistake because I cannot find much information about this problem, or I am doing it completely wrong.
Any help would be greatly appreciated.
I think you should do smth like this
public Mono<InternetPackageDto> toDto(InternetPackage entity) {
var internetPackage = new InternetPackageDto();
internetPackage.setName(entity.getName());
internetPackage.setPrice(entity.getPrice());
internetPackage.setId(entity.getId());
return Mono.zip(Mono.just(internetPackage), entity.getExtras().collectList(), entity.getAttributes().collectList())
.flatMap(tu->{
var dto = tu.getT1();
dto.setExtras(tu.getT2()); //To make it work in my local i made entity.getAttributes() as Flux<String> so here you will probably need to use .stream().map(dbItem->dbItem.getPropertyName())
dto.setPackageAttributes(tu.getT2());
return Mono.just(dto);
});
}
I'm trying to use findBy... in my repository to get a Savingaccount object passing a nested attribute(name) as a parameter. Currently I'm using:
Mono<SavingAccount> findByOwnerName(String name);
but I'm getting this error: No property name found for type Owner! Traversed path: SavingAccount.owner.
My repository:
package com...SavingAccMS.Repository;
import com.everis.SavingAccMS.Model.Owner;
import com.everis.SavingAccMS.Model.SavingAccount;
import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
import reactor.core.publisher.Mono;
public interface SavingAccountRepo extends ReactiveMongoRepository<SavingAccount, String>
{
Mono<SavingAccount> findByNumber(String number);
//This one is the problem
Mono<SavingAccount> findByOwnerName(String name);
Mono<SavingAccount> findByOwner(Owner owner);
}
My Entity:
package com...SavingAccMS.Model;
import java.security.acl.Owner;
import javax.validation.constraints.NotBlank;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import lombok.Data;
#Data
#Document(collection = "SavingAccs")
public class SavingAccount
{
#Id
private String id;
#NotBlank
private String number;
#NotBlank
private Owner owner;
#NotBlank
private String currency;
#NotBlank
private double balance = 0.00;
#NotBlank
private String status;
}
package com...SavingAccMS.Model;
import org.springframework.data.mongodb.core.mapping.Document;
import lombok.Data;
#Data
#Document(collection = "Owners")
public class Owner
{
public String dni;
public String name; //findBy this attribute is required.
}
According to your imports, the Owner in your SavingAccount refers to java.security.acl.Owner, not the one you defined yourself in om...SavingAccMS.Model.Owner. The former does not carry a name attribute.
I'm not certain but I don't think you can find the owner name in hibernate like that.
I would try the following!
#Query("SELECT * FROM SavingAccount where owner.name = :name")
Mono<SavingAccount> findByOwnerName(#Param("name") String name);
I have a couple of services who use the same form of table to store translations, so I moved the translation entity into a shared project and try to have a unidirectional #OneToMany mapping on that entity. However I keep getting following exception
Caused by: org.hibernate.AnnotationException: Use of #OneToMany or #ManyToMany targeting an unmapped class: com.examples.blog.Post.translations[com.examples.shared.domain.Translation]
my Post class looks like this
package com.examples.blog.domain;
import com.examples.shared.domain.Translation;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
import java.io.Serializable;
import java.util.List;
#Data
#Entity
#Table(name = "POSTS")
#Builder
#NoArgsConstructor
#AllArgsConstructor
public class Currency implements Serializable {
#Id
#GeneratedValue(generator = "system-uuid")
#GenericGenerator(name = "system-uuid", strategy = "uuid")
private String id;
private String author;
#Embedded
private Source source;
#OneToMany(cascade = CascadeType.ALL,
orphanRemoval = true)
#JoinColumn(name = "entity_id")
List<Translation> translations;
}
and my shared Translation class looks like this:
package com.examples.shared.domain;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
import java.io.Serializable;
#Entity
#Table(name = "TRANSLATIONS")
#Data
#Builder(toBuilder = true)
#NoArgsConstructor
#AllArgsConstructor
public class Translation implements Serializable {
#Id
#GeneratedValue(generator = "system-uuid")
#GenericGenerator(name = "system-uuid", strategy = "uuid")
private String id;
#Column(name = "language")
private String language;
#Column(name="translation")
private String translation;
#Column(name="entity_id")
#ManyToOne
private String entityId;
}
Anyone can help me figure out what I'm doing wrong here?
Seems like hibernate is not aware of com.examples.shared.domain.Translation entity.
You should provide hibernate a list of classes or packages where it should look for #Entities classes.
If you use Spring Boot use #EntityScan(basePackages="com.examples.shared.domain").
If you use Spring + Hibernate integration, use LocalContainerEntityManagerFactoryBean.setPackagesToScan("com.examples.shared.domain")
If you use plain hibernate, add a corresponding entry to persistence.xml or hibernate.cfg.xml:
<hibernate-configuration>
....
<mapping class="com.examples.shared.domain.Translation"/>
</session-factory>
</hibernate-configuration>
Or for java config see docs: http://docs.jboss.org/hibernate/orm/5.3/userguide/html_single/Hibernate_User_Guide.html#bootstrap-bootstrap-native-registry-MetadataSources-example
Below statement is causing you issue:
#Column(name="entity_id")
#ManyToOne
private String entityId;
Instead of String entityId, you should mention relationship with a valid entity class. Here entityId is of type String which is obviously not a declared entity.
You are mapping 2nd class in onetomany in one class but mapping manytoone to a string instead of class.
Change
#ManyToOne
private String entityId;
to
#ManyToOne
private Currency entityId;
See this