Can't save "Many"-Entity of #OneToMany with Spring-Boot & Spring-JPA - spring

I'm using Spring Boot and MySQL. I followed this link for setting everything up and I'm able to connect to MySql and read/write data. But there is an 1:n-relationship and I'm not able to save entities of the many side:
#Entity
public class OneSideOfRelationship {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long oneId;
private String someText;
#OneToMany(mappedBy="oneId")
private List<ManySideOfRelationship> manySide;
[Constructor / Getter / Setter]
}
#Entity
public class ManySideOfRelationship {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long manyId;
#ManyToOne(targetEntity=OneSideOfRelationship.class)
#JoinColumn
private long oneId;
private String someMoreText;
[Constructor / Getter / Setter]
}
#Transactional
public interface OneDao extends CrudRepository<OneSideOfRelationship, Long> {}
#Transactional
public interface ManyDao extends CrudRepository<ManySideOfRelationship, Long> {}
If I do this in my controller:
[...]
#Autowired
#private ManySideOfRelationship manyDao;
[...]
ManySideOfRelationship many = new ManySideOfRelationship();
many.setOneId(1L);
many.setSomeMoreText("Text");
manyDao.save(many);
[...]
I got:
org.springframework.orm.jpa.JpaSystemException: could not get a field value by reflection getter of com.package.database.OneSideOfRelationship.oneId; nested exception is org.hibernate.PropertyAccessException: could not get a field value by reflection getter of com.package.database.OneSideOfRelationship.oneId
Out of my application.properties:
spring.datasource.url = jdbc:mysql://myurl:myport/mydatabase
spring.datasource.username = myusername
spring.datasource.password = mypassword
spring.jpa.hibernate.ddl-auto = update
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
And something out of pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
Hope somebody has an idea.

The oneId must be datatype of OneSideOfRelationship not long.
#ManyToOne(targetEntity=OneSideOfRelationship.class)
#JoinColumn
private OneSideOfRelationship oneId;

Related

Spring boot with H2 - Not a managed type

I am having a problem while starting my Spring Boot application:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'coffeeService': Unsatisfied dependency expressed through field 'coffeeRepository': Error creating bean with name 'coffeeRepository' defined in com.coffeetime.coffeeshop.repository.CoffeeRepository defined in #EnableJpaRepositories declared on CoffeeshopApplication: Not a managed type: class com.coffeetime.coffeeshop.domain.Coffee
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'coffeeRepository' defined in com.coffeetime.coffeeshop.repository.CoffeeRepository defined in #EnableJpaRepositories declared on CoffeeshopApplication: Not a managed type: class com.coffeetime.coffeeshop.domain.Coffee
Caused by: java.lang.IllegalArgumentException: Not a managed type: class com.coffeetime.coffeeshop.domain.Coffee
The version of Spring Bot is 3.0 and Java is 17 (Most updated ones from Initialzr).
I want to use H2 as in-memory database:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>javax.persistence-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
The package hierarchy is convenient to scan entities. So, I think it is not necessary to add #EntityScan (I tried it as well)
File structure
Here is application.properties:
spring.datasource.url=jdbc:h2:mem:coffeeshopdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=pass1234
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.show-sql=true
spring.h2.console.enabled=true
spring.jpa.defer-datasource-initialization=true
Repository
import org.springframework.data.jpa.repository.JpaRepository;
import com.coffeetime.coffeeshop.domain.Coffee;
public interface CoffeeRepository extends JpaRepository<Coffee, Long>{
}
And the entity:
#Entity
#Table(name = "coffee")
public class Coffee {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
#Column(name = "name")
#NotEmpty(message = "Coffee name cannot be empty")
private String name;
#Column(name = "amount")
#NotNull(message = "Coffee price cannot be empty")
#Min(value = 0, message = "Coffee price must be greater than or equal to 0")
private BigDecimal amount;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
}
I checked the similar problem in this thread, no any answer worked. I suspect about H2.
Thanks
I tried using #EntityScan and playing with application.properties. But still same error.
I found the problem. Spring Boot 3.0.0 version started using jakarta instead of javax.persistence. Reorganizing the imports solved the problem.

Quarkus Reactive with Vert.x and Hibernate Reactive / java.lang.NullPointerException: Cannot store to object array because "this.loadedState" is null

i am trying to use quarkus reactive with vert.x and hibernate reactive.
this is my pom.xml:
<quarkus-plugin.version>1.12.2.Final</quarkus-plugin.version>
and
<quarkus.platform.version>1.12.2.Final</quarkus.platform.version>
with:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-reactive</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-reactive-jackson</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-reactive-mysql-client</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-vertx-web</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-reactive</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-reactive-pg-client</artifactId>
</dependency>
this is my application.properties file:
# postgres-configuration
quarkus.datasource.db-kind=postgresql
quarkus.datasource.username=partner_usr
quarkus.datasource.password=postgrespw
quarkus.datasource.reactive.url=vertx-reactive:postgres://localhost:3310/partnerdb
# test, but not working (schema's won't created)
quarkus.hibernate-orm.database.generation.create-schemas=true
# working (drop-and-create only on mysql, not on postgres)
quarkus.hibernate-orm.database.generation=drop-and-create
quarkus.hibernate-orm.log.sql=true
quarkus.http.cors=true
Then, i have following entities:
#Data
#MappedSuperclass
public abstract class IdEntity {
#Id
#SequenceGenerator(name = "entitySeq", sequenceName = "entitiy_id", allocationSize = 1, initialValue = 5)
#GeneratedValue(generator = "entitySeq", strategy = GenerationType.AUTO)
private Long id;
}
#Data
#Entity
#EqualsAndHashCode(callSuper = true)
public class Person extends IdEntity {
private String firstName;
private String lastName;
public Person() {
}
#ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Address personAddress;
}
#Data
#Entity
#EqualsAndHashCode(callSuper = true)
public class Address extends IdEntity {
private String street;
private String houseNumber;
private int postalCode;
private String city;
#OneToMany(orphanRemoval = true, mappedBy = "personAddress", fetch = FetchType.LAZY)
private List<Person> persons = new ArrayList<>();
public Address() {
}
}
Now, i am calling a reactive web-service with a reactive db access:
#Path("/person")
#ApplicationScoped
public class PersonResource {
#Inject
io.vertx.mutiny.pgclient.PgPool sqlClient;
#Inject
Mutiny.Session mutinySession;
#GET
//#Produces(MediaType.APPLICATION_JSON)
#Path("/list-persons")
#Route(path = "/list-persons", methods = HttpMethod.GET, produces = MediaType.APPLICATION_JSON)
#Transactional
public Multi<Person> listAllPersons() {
// return sqlClient.query("SELECT * FROM Person ORDER BY lastName ASC").execute()
// .onItem().transformToMulti(set -> Multi.createFrom().iterable(set))
// .onItem().transform(this::transformPersons);
return mutinySession.createQuery("SELECT f FROM Person f ORDER BY f.lastName")
.getResults().onItem().transform(this::transformObject);
}
private Person transformObject(Object f) {
return (Person)f;
}
private List<Object> transformPersons(Object f) {
final Person person = (PartnerMockEntity)f;
final List<Object> bogus = new ArrayList<>();
bogus.add(partner);
return bogus;
}
}
Exception:
Resulted in: com.fasterxml.jackson.databind.JsonMappingException: Cannot store to object array because "this.loadedState" is null (through reference chain: de.subito.model.Person["personAddress"]->de.subito.model.Address["person"])
I tried to use :
FetchType.EAGER on Address in Person
I removed the #OneToMany Relation in Address: this solves the error (yay), but the addresses won't be returned in the resulting json (id is existing, but the values are not fetched)
The questions is, how can i fetch in reactive those kind of relations without getting errors?
Or do i need a angular page in order to display this correctly?
Somehow i forgot about how fetchType.Lazy works.
Simply add a join fetch into the hql and everything works as expected.
SELECT p from Person p left join fetch p.personAddress
When using this query, there's no session/closed or any other exception thrown and the json result will be displayed as expected.
Additional note: in order to avoid recursive serialization, it is required to use the
#JsonManagedReference and #JsonBackReference
Annotations, depending on your needs to your relations.

Why do I see different behavior on this Spring repository when it is imported as a dependency into another project?

I am seeing different behavior from a Spring annotated repository when I run my project independently vs. when I add the project as a maven dependency. The delete method on the Spring CrudRepository seems to be where I am seeing the strange behavior.
Here are what I believe are the pertinent pieces of my interface and related entities:
#Repository
public interface JpaProfileRepo extends ProfileRepo, JpaRepository<UserProfileEntity, Long>, GsonProvider {
#Transactional
default void removeProfile(Profile profile){
if(profile == null){
throw new MissingKeyDataException("Missing valid ProfileModel object during removeProfile");
}
UserProfileEntity entity = findEntityByKeys(profile);
if (entity == null) throw new DoesNotExistException();
try{
this.delete(entity);
} catch (EmptyResultDataAccessException ex) {
throw new DoesNotExistException();
}
}
}
public interface ProfileRepo {
void removeProfile(Profile profile);
}
#Entity
#Table(name="user_profiles")
public class UserProfileEntity {
#Id
#SequenceGenerator(name = "user_profiles_id_seq", sequenceName = "user_profiles_id_seq", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_profiles_id_seq")
private Long id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "user_id")
private UserEntity user;
#NotNull
#Column(name = "permissions", columnDefinition="TEXT")
private String permissions;
}
#Entity
#Table(name="users", uniqueConstraints ={
#UniqueConstraint(columnNames={"email_address"})
})
public class UserEntity {
#Id
#SequenceGenerator(name = "users_id_seq", sequenceName = "users_id_seq", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "users_id_seq")
private Long id;
#NotNull
#Column(name = "email_address", updatable = false)
private String emailAddress;
#Column(name = "preferences", columnDefinition="TEXT")
private String preferences;
When I debug through the removeProfile method on the original project, I run a query on the user_profiles table before and after I execute this.delete(entity). I can confirm the table entry for the entity passed into the removeProfile method is present before that line runs and deleted after that line runs.
When I debug the same code when it is being called from the parent project, I run the same query for the presence of the table entry for the entity passed into the removeProfile method before and after. In this case the table entry is not deleted, but I don't see any exception thrown or any other error - the row just doesn't get deleted as I would expect.
One additional wrinkle I want to mention is that I am using IntelliJ and have my local database connection configured in both projects. When I run select * from pg_catalog.pg_tables; from a postgres console in the original project, I see the user_profiles and users tables come back in the list of tables on the database. When I run the same query on the parent project, I don't see the user_profiles and users tables in the list of tables on the database, I only see the default postgres tables. Is it possible I have some sort of error based on connecting to the same local database from two separate projects? If that was the case I would expect the parent project to actually fail to connect to the database, rather than show a successful connection but quietly fail to run a database query.
For reference here is everything database related from the two project properties files:
Original project:
spring.jpa.database=default
spring.jpa.generate-ddl=true
spring.jpa.show-sql=true
datasource.platform=postgres
datasource.jdbc-url=jdbc:postgresql://localhost:5432/database
sql-dialect=org.hibernate.dialect.PostgreSQLDialect
datasource.hbm2ddl.auto=
datasource.username=user
datasource.password=
Parent project:
spring.jpa.database=default
spring.jpa.generate-ddl=true
spring.jpa.show-sql=true
datasource.platform=postgres
datasource.jdbc-url=jdbc:postgresql://localhost:5432/database
sql-dialect=org.hibernate.dialect.PostgreSQLDialect
datasource.hbm2ddl.auto=
datasource.username=user
datasource.password=
Seems possible to me the issue could be Spring related, JPA/Hibernate related, Maven related, Postgres related, IntelliJ related, or some delightful combo. Any ideas on what I'm missing here?
For reference, here are the versions I'm using:
Spring: 2.0.3
Postgres: 9.4-1206-jdbc42
Maven: 2.7
And here are our hibernate/JPA dependencies:
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>2.0.5.RELEASE</version>
</dependency>
And here is the db configuration class I have:
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(
entityManagerFactoryRef = "entityManager",
transactionManagerRef = "transactionManager",
basePackages = {"com.repositories"}
)
public class DbConfig {
#Value("${datasource.hbm2ddl.auto}")
private String ddlAuto;
#Value("${sql-dialect}")
private String dialect;
#Bean
#ConfigurationProperties(prefix="datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
#Bean
public EntityManagerFactoryBuilder entityManagerFactoryBuilder() {
return new EntityManagerFactoryBuilder(new HibernateJpaVendorAdapter(), new HashMap<>(), null);
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManager(
EntityManagerFactoryBuilder builder,
#Qualifier("dataSource") DataSource dataSource)
{
Map<String, Object> properties = new HashMap<String, Object>();
properties.put("hibernate.dialect",dialect);
properties.put("hibernate.hbm2ddl.auto",ddlAuto);
return builder
.dataSource(dataSource)
.persistenceUnit("object")
.properties(properties)
.packages("com.entities")
.build();
}
#Bean
public PlatformTransactionManager transactionManager(
#Qualifier("entityManager") EntityManagerFactory
entityManagerFactory
) {
return new JpaTransactionManager(entityManagerFactory);
}
}

How to save #lob data using spring JPA repository

I want to save #lob(blob) data into DB using JPA repository.
I am trying something like below
User user = new user();
user.setProfile(<<BLOB DATA>>);
I want to set user profile as blob data and save to db
we use #Lob to save the data in BLOB or CLOB
Entity:
#Entity
#Table(name="USER_LOB_TABLE")
public class User {
#Id
private Long userId;
#Lob
#Column(name="PROFILE")
private byte[] profile;
//getters and setters
}
JpaRepository:
public interface UserRepository extends JpaRepository<User,Long>{}
Service layer:
userRepository.save(new User(1L,"hellodgasdgasdgasdgadsgas".getBytes()));
output:
user_id,profile
1,BLOB
Why not use Spring Content JPA?
pom.xml
<!-- Java API -->
<dependency>
<groupId>com.github.paulcwarren</groupId>
<artifactId>spring-content-jpa-boot-starter</artifactId>
<version>0.0.11</version>
</dependency>
<!-- REST API -->
<dependency>
<groupId>com.github.paulcwarren</groupId>
<artifactId>spring-content-rest-boot-starter</artifactId>
<version>0.0.11</version>
</dependency>
User.java
#Entity
public class User {
#Id
private Long userId;
#ContentId
private String contentId;
#ContentLength
private long contentLength = 0L;
// if you have rest endpoints
#MimeType
private String mimeType = "text/plain";
JpaRepository
public interface UserRepository extends JpaRepository<User,Long>{}
UsersContentStore.java
#StoreRestResource(path="usersContent")
public interface UsersContentStore extends ContentStore<User, String> {
}
This will also give you REST Endpoints (# /usersContent) for handling your user's content.

Spring Data JPA repository findAll() method returns null List

I am using Spring Data JPA:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.7.1.RELEASE</version>
</dependency>
with Spring 4.3.7.RELEASE and Hibernate 5.2.9.Final.
When I query using findAll, the List returns contains null values.
Entity:
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#EqualsAndHashCode
#Entity
public class Etudiant implements Serializable {
/**
* Serial version UID
*/
private static final long serialVersionUID = -1982480763983112005L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "idEtudiant")
private Integer idEtudiant;
#Column(name = "nomEtudiant")
private String nomEtudiant;
#Column(name = "prenomEtudiant")
private String prenomEtudiant;
#Column(name = "adresse")
private String adresse;
#Column(name = "dateNaissance")
private Date dateNaissance;
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "etudiant_cours", joinColumns = #JoinColumn(name = "idEtudiant", referencedColumnName = "idEtudiant"), inverseJoinColumns =
#JoinColumn(name = "idCours", referencedColumnName = "idCours"))
private List<Cours> cours;
}
NB: Note that the problem is not from lombock, I had tested with getters and setters.
Repository:
#Repository
public interface EtudiantRepository extends JpaRepository<Etudiant, Integer> {
}
Service:
#Service
public class EtudiantServiceImpl {
#Autowired
EtudiantRepository etudiantRepository;
List<Etudiant> lst = new ArrayList<Etudiant>();
public List<Etudiant> getAllEtudiant() {
lst = this.etudiantRepository.findAll();
return lst;
}
}
In debug screenshot, it can be seen that etudiantRepository is null.
Maybe you are missing #EnableJpaRepositories annotation in your Configuration.
EtudiantServiceImpl is being instantiated using Dependency Injection or with the new keyword?
Finally I found the solution :
change spring version from 4.3.7.RELEASE to 4.3.10.RELEASE
you need to use context:component-scan annotation into xml configuration for scanning base package and repository package, you can find code below :
<jpa:repositories base-package="com.demo.test.repository" />
<context:component-scan annotation-config="true"
base-package="com.demo.test" />
and if findall() return null value that means table dose not having data, it is normal behavior.
and also check your datasource and entity manager connection

Resources