Spring Data Repository - composite key & don't need to save entity - jpa

I'm working with a third party database that is read-only. I have the following Spring Data repository:
public interface FolderRepository extends Repository<Folder, Integer> {
#Query(value = "SELECT f.folderId, a.fileId, a.fileName, " //selecting other columns in my app
+ "FROM User.functionSys(:binData) f "
+ "LEFT JOIN User.vFile a "
+ "ON f.fileId = a.fileId "
+ "group by f.folderId, a.fileId, a.fileName",
nativeQuery = true)
List<Folder> getFolders(#Param("binData") byte[] binData);
}
Folder id and file id form an unique key. So, my folder entity looks like this:
#Entity
#Data
public class Folder implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
private FolderFileKey id;
private String fileName;
// several other fields in my app
}
#Embeddable
#Data
class FolderFileKey implements Serializable {
private static final long serialVersionUID = 2L;
private Integer folderId;
private Integer fileId;
}
The problem is that I really want a list of File objects where each File object contains a list of Folders (the same file id may be in several different folders):
#Data
public class FileDto {
private Integer fileId;
private String fileName;
private List<Folder> folders;
}
#Data
public class FolderDto {
private Integer folderId;
private String folderName;
}
I know that I could write a service to transform a Folder entity into the FileDto and FolderDto but is there a way to use Spring Data projections or rewrite the entities to achieve the structure wanted in the Dtos?
Update
User.functionSys(:binData) is a table-valued function (so it returns a table).

Related

JPA how to set foreign id - in Embeddable id - that is generated

My use case is: I have a Product with multi language name. To have at most one name per language a translation should be identified by locale + productId.
My problem is to get it working with a generated productId. This are the entities:
e.g. in oracle i get: "ORA-01400: cannot insert null into ."PRODUCT_NAME"."FOREIGN_ID""
Product:
#Entity
#Data
public class Product {
#Id
#GeneratedValue
private Long id;
#Column(unique = true)
private String articleNumber;
/**
* Localized name of the product.
*/
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
#MapKey(name = "nameId.locale")
private Map<Locale, ProductName> names = new HashMap<>();
}
ProductName:
#Entity
#Data
public class ProductName {
#EmbeddedId
private TranslationId nameId;
private String name;
}
TranslationId:
#Embeddable
#Data
public class TranslationId implements Serializable {
private static final long serialVersionUID = 3709634245257481449L;
#Convert(converter = LocaleConverter.class)
private Locale locale;
private Long foreignId; //<-- this is null, should reference product
}
Is there a way to get this working without having to save the product first without the name? Without a generated id it is working of course - i just set same id for both.
I would like to re-use the translation id for other translated fields of other entities.

Spring JPA using primary key within #Embeddable class

In my application i have a scenario to fetch data from entity based on give input code and date.
The combination of code and date will be unique and will return a single record.
Below is my entity
class JpaEntity
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private id ;
private String code;
private Date date;
private title;
//Getters and Setters
}
I have tried below approcah by changing the entity.
class JpaEntity
{
private String title;
//Getters and setters
#EmbededId
private EntityId entityID
#Embedable
public static class EntityId implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private id ;
private String code;
private Date date;
//Getters and Setters
}
}
I am using the entity to search based on code and date
public interface PersistentDAO extends JpaRepository<JpaEntity,String> {
{
#Query("SELECT cal FROM JpaCalendar cal" + " WHERE cal.calendarId.currencyCode=:currencyCode "
+ " AND cal.calendarId.date=:date")
Optional<JpaCalendar> findById(String currencyCode, Date date);
JpaEntity findByID(String code,Date date)
}
But the JPA is throwing error saying Component Id is not found.
is it mandatory all the field in #Embedable are primary?
is it possible #Embedable class (composite id) contain the both primary and non-primay keys.
Since i am not supposed to change the structure of the table is there any way to achieve following:
Fetch record based on give code and date.
Insert new record where in id the primary key should be auto incremented
Please suggest.
Use #Embedded & #Embeddable and don't use static class inside class
class JpaEntity
{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private id ;
#Embedded
private CodeDate codeDate;
private title;
}
#Embeddable
class CodeDate {
private String code;
private Date date;
}
You can use Jpa method naming query and create a CodeDate object call like this
public interface PersistentDAO extends JpaRepository<JpaEntity,String> {
{
JpaEntity findByCodeDate(CodeDate codeDate);
}

How to query for entities by their string collection values LIKE

I have the following entity:
#Entity
public class SystemLogEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private long creationTime;
private String thread;
private int severity;
#Lob
private String message;
#ElementCollection(fetch = FetchType.EAGER)
#Lob
private List<String> stacktrace;
...
}
My Respository implements JpaSpecificationExecutor, which allows me to use Specifications to filter my db requests:
#Repository
public interface SystemLogRepository extends JpaRepository<SystemLogEntity, Long>, JpaSpecificationExecutor<SystemLogEntity> {
public List<SystemLogEntity> findAll(Specification spec);
}
For the simple field of the SystemLogEntity this works fine, the Predicate are straight forward.
Also if I filter for an exact item in a collection, the Predicate are still straight forward (in).
But how can I filter my SystemLogEntity after a stack trace collection item which is LIKE a given value?
In other words, I would e.g. like to filter SystemLogEntity after the term NullpointerException. Is this even possible with Predicate?
I hope this will work:
Specification<SystemLogEntity> stacktraceLike(String stacktrace) {
return (root, query, cb) -> cb.like(root.join("stacktrace"), "%" + stacktrace + "%");
}
More examples...

Spring data jpa JOIN does't work in #Query

I am using spring-data-jpa. I wrote a native query but it doesn't work. Here is my entity classes:
#Entity
#Table(name="view_version")
public class ViewVersionDom {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
#ManyToOne
#JoinColumn(name="view_id")
private ViewDom view;
private Integer version;
#ManyToOne
#JoinColumn(name="datasource_param_id")
private DatasourceParamDom datasourceParam;
private String description;
#Column(name="created_date")
private Date createdDate;
#Entity
#Table(name="view_permission")
public class ViewPermissionDom extends BaseDom {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
#ManyToOne
#JoinColumn(name="view_id")
private ViewDom view;
#ManyToOne
#JoinColumn(name="user_id")
private UserDom user;
#ManyToOne
#JoinColumn(name="group_id")
private GroupDom group;
private Boolean read;
private Boolean write;
private Boolean execute;
Here is the query:
#Query(value = " SELECT v FROM ViewVersionDom v LEFT JOIN ViewPermissionDom vp ON v.view.id = vp.id "
+ " where (v.view.user.id = ?1 OR (vp.read=true and (vp.user.id=?1 or vp.user.id is NULL and vp.group.id is NULL or vp.group.id in (?2)))) "
+ " ORDER BY v.view.name", nativeQuery=true)
public List<ViewVersionDom> findUserViews(Long userId, List<Long> groupIds);
At first when I didn't write nativeQuery=true the application didn't build and I got an exception 'path expected for join jpa'. When I set the settings nativeQuery=true the application is started, but when I call the function I got the following error:
org.hibernate.engine.jdbc.spi.SqlExceptionHelper - [ERROR: relation "viewversiondom" does not exist Position: 16]
org.hibernate.exception.SQLGrammarException: could not extract ResultSet]
Does there any other settings or annotation that will resolve the problem?
I have searched in google, but in all cases 2 tables connected with each other directly.
Your query is not a SQL query (assuming, you don't have a column v in one for your tables).
Also the Table viewversiondom doesn't exist or is not accessible to the database user used for the connection.
Also when mapping native queries to domain objects you should have a look at https://jira.spring.io/browse/DATAJPA-980

Querying Embedded document in MongoDB using Mongo Template

I have the above domain structure where I have list of Companies in the product and the aim is not make entry in mongoDB when I have exact match for companies & productId already present in the DB.
#Entity
public class Mobile {
#Id
private Integer id;
private String imei;
private Product productInfo;
// ...
}
#Entity
public class Product {
#Id
private Integer id;
private String productId;
private List<Company<?>> companies;
// ...
}
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY, property = "type")
#JsonSubTypes({
#JsonSubTypes.Type(name= "samsung", value = Samsung.class),
#JsonSubTypes.Type(name= "htc",value = Htc.class)})
public class Company<T> implements Serializable {
private static final long serialVersionUID = -8869676577723436716L;
private T companyInfo;
private String type;
// ...
}
I am using mongo template and I have tried to use find as shown below but id didn't work
template.find(Query.query(Criteria.where("product.companies").is(companList),Mobile.class);