How to create the table without #Id field in spring using jpa? - java

I am using spring boot and jpa to create the table but I need to create table without #Id primary key column.It is not giving me to make the table without this #Id field. How to get this using spring data jpa?
LetterDoc.java
package com.ashwin.springsecurityangular.model;
import java.io.Serializable;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonIgnore;
#Entity
#Table(name = "letter_doc")
public class LetterDoc implements Serializable {
private static final long serialVersionUID = 1L;
#ManyToOne(fetch = FetchType.EAGER, optional = false,cascade=CascadeType.PERSIST)
#JoinColumn(name = "letterNo")
#JsonIgnore
private Letter letter;
#ManyToOne(fetch = FetchType.EAGER, optional = false,cascade=CascadeType.PERSIST)
#JoinColumn(name = "documentId")
#JsonIgnore
private Document document;
private String docFile;
//i omitted getters and setters and both constructor
}
It ask me the #Id field need.So there is error like:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: No identifier specified for entity: com.ashwin.springsecurityangular.model.LetterDoc
In this table i am avoided to make #Id field but it is not giving me.How to achieve this?

JPA Specification clearly narrates that an Entity class must have a unique, immutable ID. However there are some hacks you can give them a try.
1) Maintain UUID for this purpose.
#Id
#Column(columnDefinition = "BINARY(16)")
private UUID uuid;
2) Create a DTO/POJO representation of data fields in view layer, then execute a SQL Native query, then map the result set to your class

USE JPA PROJECTIONS
In your case you dont have a primary key so use JpaProjections to get the fields you want
first declare Entity as
#Entity
#Immutable
set your Repository
public interface AddressView {
String getZipCode();
}
Then use it in a repository interface:
public interface AddressRepository extends Repository<Address, Long> {
#Query("SELECT ADDRESS from TABLE WHERE address = ?1")
AddressView getAddressByState(String state);
}
note ADDRESS entity in above is a placeholder
just make it
Public class ADDRESS{
#Id
Long id;

Related

Error while starting Spring boot application with external JAR containing the beans

I have a Spring Boot Application created from the Spring Initializer, I added an external JAR (manually in build path libraries) who containing the beans. The beans are annotated with #Entity and #json...
The problem is that when starting the application I have the error below. If I copy the beans into the project as a simple bean, the project start correctly.
Error creating bean with name 'userRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class org.xxxxxxx.domain.User
Please any help is greatly appreciatedĀ 
Here is an example of a bean from the JAR.
package org.xxxxxxx.domain;
import java.io.Serializable;
import java.sql.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
#Entity
#Table (name="userTable", uniqueConstraints=#UniqueConstraint(columnNames={"nom"}))
public class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
#Column(name="nom", unique=true, nullable=false)
private String name;
private String motsdepasse;
private String token;
#ManyToOne
private UserGroupe groupe;
// #Column(columnDefinition="boolean default false")
private boolean desactive;
// #Column(columnDefinition="boolean default false")
private boolean finalPwd;
private boolean deleted;
private Date datePassword;
#ManyToOne
private Branch branche;
//getters + setters
By default all packages below your main configuration class (the one annotated with #EnableAutoConfiguration or #SpringBootApplication) will be searched. You can customize entity scanning locations using the #EntityScan annotation:
spring docs

Spring Boot JPA - Define a One to Many relationship

i'm trying to build a simple full stack tic-tac-toe application, but i've some problem defing a one-to-many relationship.
here the context, we have a main table Games:
CREATE TABLE `tictactoe`.`games` (
`idgames` INT NOT NULL AUTO_INCREMENT,
`gridConf` VARCHAR(45) NOT NULL,
`playerNum` VARCHAR(45) NOT NULL,
PRIMARY KEY (`idgames`));
and a secondary table, Gamesteps:
CREATE TABLE `tictactoe`.`gamesteps1` (
`idgamesteps` INT NOT NULL AUTO_INCREMENT,
`idgame` INT NOT NULL,
`step` VARCHAR(45) NOT NULL,
PRIMARY KEY (`idgamesteps`));
i'd like to define a relation One (Game) to Many (Gamesteps),
where the combo Gamesteps.idgamesteps and Gamesteps.games is primary key on the Gamesteps table.
i have two doubts:
1- how should i define my db tables? are my queries rights or do i need an explict foreing key?
2 -JPA annotations:
here my entities:
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class Games {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer idgames;
private String gridConf;
private Integer playerNum;
#OneToMany(mappedBy = "idgames")
private Set<GameSteps> gameSteps;
//all setter/getters
secondary table:
import javax.persistence.Entity;
import javax.persistence.Id;
#Entity
public class GameSteps {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer idGameSteps;
#ManyToOne
#JoinColumn(name = "idgames", referencedColumnName = "idgames")
private Integer idgame;
private String step;
//all setter/getter
i'm trying to archive is the possibility to do a Save/findAll operation throught my CRUDRepository interface on the main entity (Games) and do an automatic Save/findAll on all the others subEntities (gamesteps).
for me is not clear where i should use the #OneToMany or #ManyToOne annotations.
For now i'm only getting exceptions.
if needs others info just ask, any type of help / documentation will be really approciated!
Thanks!
Following #Smutje comment i've change to:
public class GameSteps {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer idGameSteps;
#ManyToOne
#JoinColumn(name = "idgames", referencedColumnName = "idgames")
private **Games** idgame;
and
#OneToMany(mappedBy = "**idgame**")
private Set<GameSteps> gameSteps;
but got:
java.sql.SQLSyntaxErrorException: Unknown column 'idgames' in 'field list'
If you want Gamesteps.idgamesteps and Gamesteps.games to be primary key on the Gamesteps table. You have to use the tags #EmbeddedId and #Embeddable, your composite key has to be another class.
The primary key fields are defined in an embeddable class. The entity contains a single primary key field that is annotated with #EmbeddedId and contains an instance of that embeddable class.
Something like this
import javax.persistence.*;
#Entity
public class GameSteps {
#EmbeddedId
private GameStepsPK pk;
private String step;
// getters and setters
GameStepsPK would be the composite key
import java.io.Serializable;
import javax.persistence.*;
#Embeddable
public class ExploitationEvaluationPK implements Serializable {
private static final long serialVersionUID = 1L;
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer idGameSteps;
#ManyToOne
#JoinColumn(name = "idgames", referencedColumnName = "idgames")
private Games idgames;
You can also read about this here
I hope this helps

Spring data jpa and entities with some kind of relationship

I'm writing a sample app using the HR schema on an Oracle db 18c.
I'm using Spring boot 2, Spring Data Jpa and Spring Rest.
I'm working on Regions' table (that contains two fields: region_id and region_name) and countries table (that contains three fields: country_id, country_name and region_id).
I can manage all CRUD operation on Regions' table if its entity doesn't contain the relationship #OneToMany with Country's entity when I add it the application return me a 415 error (non supported method) that have no sense!
Here it is my code:
Region Entity:
package it.aesys.springhr.entities;
import javax.persistence.*;
import com.fasterxml.jackson.annotation.JsonBackReference;
import java.util.List;
/**
* The persistent class for the REGIONS database table.
*
*/
#Entity
#Table(name="REGIONS")
#NamedQuery(name="Region.findAll", query="SELECT r FROM Region r")
public class Region {
#Id
#GeneratedValue(generator="REGIONS_SEQ", strategy=GenerationType.SEQUENCE)
#SequenceGenerator(name="REGIONS_SEQ", sequenceName="REGIONS_SEQ", allocationSize=0)
#Column(name="REGION_ID", unique=true, nullable=false)
private int regionId;
#Column(name="REGION_NAME", nullable=false, length=50)
private String regionName;
//bi-directional many-to-one association to Country
#OneToMany(mappedBy="region", cascade = CascadeType.ALL)
// this annotation help me to not retrieve all countries when I find all Regions but I tried also without it and anything change
#JsonBackReference
private List<Country> countries;
// constructor, getters and setters as usual
}
Country Entity:
package it.aesys.springhr.entities;
import javax.persistence.*;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import java.util.List;
/**
* The persistent class for the COUNTRIES database table.
*
*/
#Entity
#Table(name="COUNTRIES")
#NamedQuery(name="Country.findAll", query="SELECT c FROM Country c")
public class Country {
#Id
#Column(name="COUNTRY_ID", unique=true, nullable=false, length=2)
private String countryId;
#Column(name="COUNTRY_NAME", nullable=false, length=40)
private String countryName;
//bi-directional many-to-one association to Region
#ManyToOne
#JoinColumn(name="REGION_ID")
#JsonManagedReference
private Region region;
// constructor, getters and setters as usual
}
The RegionRepository Interface is simply:
package it.aesys.springhr.dao;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import it.aesys.springhr.entities.Region;
public interface RegionRepository extends JpaRepository<Region, Integer> {
}
and the RegionService contains this method:
public void save(Region theRegion) {
regionRepository.save(theRegion);
}
and finally the RegionRestController contains this method:
#PostMapping( value= "/regions", consumes = "application/json;charset=UTF-8", produces = "application/json;charset=UTF-8")
public Region addRegion(#RequestBody Region theRegion) {
// also just in case they pass an id in JSON ... set id to 0
// this is to force a save of new item ... instead of update
theRegion.setRegionId(0);
regionService.save(theRegion);
return theRegion;
}
I'm using CURL to test this app and I tried to pass countries in different ways but no one works!
Can I resolve without using some external framework like Map Struct? Or, in this case I MUST create a new object that mapping what I receive with what I must persist?
[Edit]: I modify the last method with this code:
#PostMapping( value= "/regions", consumes = "application/json;charset=UTF-8", produces = "application/json;charset=UTF-8")
public Region addRegion(#RequestBody HashMap) {
Region theRegion= new Region();
theRegion.setRegionId(0);
theRegion.setRegionName(map.get("regionName"));
regionService.save(theRegion);
return theRegion;
}
and now it works but I'm not sure that this solution is secure because it seems so simply and so generic ...
As I edited, I modify the last method with this code:
#PostMapping( value= "/regions", consumes = "application/json;charset=UTF-8", produces = "application/json;charset=UTF-8")
public Region addRegion(#RequestBody HashMap<String, String>) {
Region theRegion= new Region();
theRegion.setRegionId(0);
theRegion.setRegionName(map.get("regionName"));
regionService.save(theRegion);
return theRegion;
}
and now it works but I'm not sure that this solution is secure because it seems so simply and so generic so if you think that it is not sure please answer and tell me another better solution!
You can use #Component in service class and controller class and #ComponentScan(basePackages = "<full package name>" in the main class. Problem may be solved.

Spring Data JPA could not determine type for property which is object of same class

I have a TestEntity and this entity can have a parent TestEntity. Spring Data JPA says Could not determine type for: abc.entity.TestEntity, at table: test_entity, for columns: [org.hibernate.mapping.Column(parent)], How can I fix this? Didn't found something on the internet or I searched for the wrong thing.
package abc.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class TestEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
private TestEntity parent;
public TestEntity(String name, TestEntity parent) {
this.name = name;
this.parent = parent;
}
public long getId() {
return id;
}
public String getName() {
return name;
}
public TestEntity getParent() {
return parent;
}
}
You have to put #OneToOne or #ManyToOne on parent.
Further you shall provide argument-less constructor.
Btw it is not spring data but the JPA provider who is giving you the error.
This question already has an answer here JPA inheritance Could not determine type for
It seems like you have got multiple TestEntity classes one with abc.entity.TestEntity package and the other with tud.swt16w2.entity package.
So import the correct Entity class i.e., import tud.swt16w2.entity.TestEntity as part of your repository class imports.
Use #ManyToOne and #JoinColumn(name = "parent_id") on your parent field.
It's not Spring Data JPA complaining but Hibernate, the underlying OR Mapper. If you model a relationship to an entity (independent on whether it's the same type or a different entity) you need to qualify the cardinalities of the relationship, i.e. either annotate it with #OneToOne or #ManyToOne depending on which semantics you'd like to achieve.

Spring JPA + CRUD - custom query doesn't allow _ characters?

I'm having troubles in creating a custom query within spring, because my Entity contains an "_" character in it's parameter's name: "game_date".
My table has a column named "game_date" as well.
I have created following method:
List<Games> findByGame_dateAndOpponent(#Param("game_date") Date game_date, #Param("opponent") String opponent);
but when I start my app, it's crashing with exception of kind: "org.springframework.data.mapping.PropertyReferenceException: No property gamedate found for type Games!". After changing a parameter name to the "gameDate" both in Entity and Query method, it stopped complaining, and is actually returning expected entries. But at the same time, it doesn't return values from the column "game_date", in the search queries, which is a simple regular column of a Date type. I have no idea what's going on with all this thing.
DB I'm using is MySql.
Here comes the code itself:
Entity:
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
#Entity
#Table(name = "games")
public class Games {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id_game")
private int id;
#Column(name = "game_date", columnDefinition = "DATE")
#Temporal(TemporalType.DATE)
private Date gameDate;
public Date getGame_date() {
return gameDate;
}
public void setGame_date(Date _game_date) {
this.gameDate = _game_date;
}
}
And a repository:
import java.sql.Date;
import java.util.List;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
#RepositoryRestResource
public interface GamesRepository extends CrudRepository< Games , Integer > {
List< Games > findById( #Param( "id" ) int id );
List< Games > findAll( );
List<Games> findByGameDateAndOpponent(#Param("game_date") Date game_date, #Param("opponent") String opponent);
}
The underscore is a reserved keyword in Spring Data JPA. It should be enough to remove it from your property and from its getters and setters and Hibernate will do the rest:
#Entity
#Table(name = "games")
public class Games {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id_game")
private int id;
//Getter and setters for id
#Column(name = "game_date")
private Date gameDate;
public Date getGameDate() {
return gameDate;
}
public void setGameDate(Date gameDate) {
this.gameDate = gameDate;
}
}
Also, in general, try to use java naming convention for variable and field names, which is mixed case with lowercase first.
See also:
Spring Data JPA repository methods don't recognize property names with underscores

Categories

Resources