Below is my entity class . I dont know how hash and value column is generating automatically :-
#Entity
#Table(name = "P_CLIENT_LINKS")
#Data
#NoArgsConstructor
public class ClientLinks {
String name;
String type;
#EmbeddedId
String clientId;
}
db table P_CLIENT_LINKS :-
those two columns (hash & value) are currently not mapped to your classes (ClientLinks) fields, as fields/member variables with the same name don't exist in your entity class
what exactly are you expecting to be stored in the database columns hash & value? if you add member vars with the same name of those columns (of course type must match also) then the JPA mapping should work fine. but you would still need to programatically set the values by calling the setter-methods of those two properties.
Related
i have a transactional entity and one of the fields is an association with a tenant.
#Entity
public class transactionalClass
....
#OneToOne
#JoinColumn(name = "tenant_id")
private Tenant tenant;
So this is generate a tenant_id (String) column in my transactionalClass but the type of my field is a object tenant type.
Now, i want to set directly a contextualised string (already have) on tenant_id column when create a new object. I have to do a getTenant and after set field(tenant object) in transactionalClass or is also possible to set string directly once i'm sure the key exists.
Thanks
I'm using spring-boot-starter-data-jdbc 2.4.2. In my domain aggregate I need to map a List of Strings that is populated from a column in another table. It is a legacy database so I have no control over the table and column names and need to use custom names. I see there is an #MappedCollection annotation, but can't see how to use it in this scenario. Below is my class:
#Data
#Table("NMT_MOVIE_THEATRE")
public class MovieTheatre {
#Id
#Column("MOVIE_THEATRE_ID")
private Long id;
#Column("ZIP_CODE")
private String zipCode;
// this comes from table NMT_CURRENT_MOVIE, column CM_ID, joined by MOVIE_THEATRE_ID
private List<String> currentMovieIds;
}
Using Spring Data JDBC, how can I create the one-to-many relation?
Wrap your String in a little entity.
#Table("NMT_CURRENTMOVIE")
class MovieId {
#Id
#Column("CM_ID")
final String id
// add constructor, equals and hashCode here or generate using Lombok
}
Then use it in the MovieTheatre. Since you don't have a column for an index, the proper collection to use is a Set
// ...
class MovieTheatre {
// ...
#MappedCollection(idColumn="MOVIE_THEATRE_ID")
Set<MovieId> currentMovieIds;
}
Note that equals and hashCode is important as well as the constructor taking all arguments used in those, since the entity is used in a Set.
I have an Entity "Person" which has following properties,
Id
Name
F-Name
Age
Address
When I call a repository function findAll() on Person, it returns a list of Persons.
List<Person> list = somefuntionToConvertIterableToList(personRepository.findAll());
this list has multiple objects of Person Type.
Person ...... Id1,Name1, F-Name1, Age1, Address1
Person .......IdN,NameN, F-NameN, AgeN, AddressN
I need to remove "Id" from all Persons, what should I do?
I know we can use "remove" to delete an element of list, but how to delete a property with in an element?
I think you need used : #JsonIgnore in Id look like:
#JsonIgnore
Field you want remove in reponse.
Or you can create DTO and put all field you want return look like :
public class PersonDTO {
//all field you want return
}
You can of course set id null or add ignores in serialization but maybe you do not want to load id at all. Usually you then would use DTO or Tuple to decide what fields to populate. So not first to populate all and then remove unneeded (I have not used your Person but just one simplified example class).
Tuple query in your repository would simply be like (JPQL):
#Query("SELECT te.name AS name, te.created as created FROM TestEntity te")
List<Tuple> findAllTuple();
This would need then do extra work to have tuple to correspond original entity when serialized. So preferably with a DTO, like:
// This class would be exactly as your Person but without that id
#AllArgsConstructor // you need the constructor for new in jpql
public class TestEntityDto {
private String name;
private LocalDateTime created;
}
while the query in your repository would be like:
#Query("SELECT NEW org.example.data.entity.dto.TestEntityDto(te.name, te.created) FROM TestEntity te")
List<TestEntityDto> findAllDto();
In Spring Data is it possible to extend a query that is generated by the find* functions of the repo interfaces?
Given following use case:
My legacy database has an inheritance by table. So given following
#Entity public class Person {
private int id;
private String className;
}
#Entity #PrimaryKeyJoinColumn(name="id") public class Musician extends Person {
String instrument;
}
#Entity #PrimaryKeyJoinColumn(name="id") public class Lawyer extends Person {
String discipline;
}
My repository for Musician:
public interface MusicianRepository extends CrudRepository<Musician, int> {
List<Musician> findAll();
}
Now an entry for a new musician in SQL would be:
insert into Person(id, className) values(1, 'Musician');
insert into Musician(id, instrument) values(1, 'piano');
When a Musician got migrated to a lawyer the old system added one row to Lawyer table without removing Musician by:
insert into Lawyer(id, discipline), values(1, 'finance');
update Person set ClassName = 'Lawyer' where ID = 1;
My MusicianRepo would now find the lawyer since the row in Musician still exists.
I would need some kind of post processor where I could extend the query by adding a where clause with "ClassName = 'Musician'" on all find* methods.
Is this possible somehow?
I think that your JPA mapping is just not correct in terms of inheritance.
I think you want to have "Joined, Multiple Table Inheritance"
Citing from here:
Joined inheritance is the most logical inheritance solution because it
mirrors the object model in the data model. In joined inheritance a
table is defined for each class in the inheritance hierarchy to store
only the local attributes of that class. Each table in the hierarchy
must also store the object's id (primary key), which is only defined
in the root class. All classes in the hierarchy must share the same id
attribute. A discriminator column is used to determine which class the
particular row belongs to, each class in the hierarchy defines its own
unique discriminator value.
Some JPA providers support joined inheritance with or without a
discriminator column, some required the discriminator column, and some
do not support the discriminator column. So joined inheritance does
not seem to be fully standardized yet.
The className column in Person would be your descriminator column. It determines the subclass to instantiate.
Your mapping would be something like this:
#Entity
#Inheritance(strategy=InheritanceType.JOINED)
#DiscriminatorColumn(name="className")
public class Person {
private int id;
private String className;
}
#Entity
#DiscriminatorValue("Musician")
public class Musician extends Person {
String instrument;
}
#Entity
#DiscriminatorValue("Lawyer")
public class Lawyer extends Person {
String discipline;
}
This way if you query for Lawyer entities JPA would automatically add the where clause to just read rows with className=Lawyer
I did not try the mapping - it should just illustrate the way you should be going.
I am using spring-data-jpa version 1.5.1.RELEASE .
My domain is :
public class MyDomain{
....
....
private String prop1;
private String prop2;
......
......
}
My JPA Specification is:
public final class MyDomainSpecs {
public static Specification<MyDomain> search(final String prop1,final String prop2) {
return new Specification<MyDomain>() {
public Predicate toPredicate(Root<MyDomain> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
// Some tests if prop1 exist .....
Predicate predicate1 = cb.equal(root.get("prop1"), prop1);
Predicate predicate2 = cb.equal(root.get("prop2"), prop2);
return cb.and(predicate1, predicate2);
}
};
}
}
My Repository :
public interface MyDomainRepository extends JpaRepository<MyDomain, Long>, JpaSpecificationExecutor<MyDomain> {
List<MyDomain> findAll(Specification<MyDomain> spec);
}
All is Working .
But my need (For performance DB tunning) is to not return and select all fields of MyDomain from DB .
I need to select only for example tree properties (prop1, prop2, prop3) , idealy in a DTO Object .
I don't want to convert My List<MyDomain> to List<MyDto> because i am tunning DB request .
So , I don't find any way to do that with spring-data-Jpa and Specification .
Any Idea ?
Thanks
This is not possible as for now. There is a ticket for this but no idea if it will be ever implmented: https://jira.spring.io/browse/DATAJPA-51
Create a special version of MyDomain (e.g. MyDomainSummary or LightMyDomain) that only includes the fields you want to map.
Basic example
Borrowed from the excellent JPA WikiBook.
Assume a JPA entity (i.e. domain class) like so:
#Entity
#Table(name="EMPLOYEE")
public class BasicEmployee {
#Column(name="ID")
private long id;
#Column(name="F_NAME")
private String firstName;
#Column(name="L_NAME")
private String lastName;
// Any un-mapped field will be automatically mapped as basic and column name defaulted.
private BigDecimal salary;
}
The SQL query generated will be similar to
SELECT ID, F_NAME, L_NAME, SALARY FROM EMPLOYEE
if no conditions (where clause) are defined. So, to generalize the basic case one can say that the number of queried columns is equal to the number of mapped fields in your entity. Therefore, the fewer fields your entity, the fewer columns included in the SQL query.
You can have an Employee entity with e.g. 20 fields and a BasicEmployee as above with only 4 fields. Then you create different repositories or different repository methods for both.
Performance considerations
However, I seriously doubt you'll see noticeable performance improvements unless the fields you want to omit represent relationships to other entities. Before you start tweaking here log the SQL that is currently issued against the data base, then remove the columns you want to omit from that SQL, run it again and analyze what you gained.