Hibernate map List<Enums> to Postgres enum - postgresql

I need to map a list of Enums to a table in postgres.
For the generic mapping of a 1:1 relation I found this post very helpful. The code looks like:
#Entity(name = "Post")
#Table(name = "post")
#TypeDef(
name = "pgsql_enum",
typeClass = PostgreSQLEnumType.class
)
public static class Post {
#Id
private Long id;
private String title;
#Enumerated(EnumType.STRING)
#Column(columnDefinition = "post_status_info")
#Type( type = "pgsql_enum" )
private PostStatus status;
//Getters and setters omitted for brevity
}
But I have no troubles to figure out a solution if PostStatus is a List<PostStatus>. Because than the definition fails.
To make it specific: I have a table, e.g. PostRelations where I can store post_id and status. For the sake of sample I can store multiple status (e.g. timebased). So how to define it properly if I have
#Entity(name = "Post")
#Table(name = "post")
public static class Post {
#Id
private Long id;
private String title;
private List<PostStatus> status;
}
The approach to define it the same way cause an exception (which seems clear because the annotation is for a enum and not for a List)
Caused by: java.lang.ClassCastException: interface java.util.List
at java.lang.Class.asSubclass(Class.java:3404) ~[na:1.8.0_212]
at org.hibernate.type.EnumType.setParameterValues(EnumType.java:86) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final]

After some research and digging into the issue I finally solved the problem thanks to the sample for proper linking and setup:
#ElementCollection
#CollectionTable(name = "post_permission", joinColumns = #JoinColumn(name = "post_id"))
private List<PostStatus4Save> status;
and a thin wrapper around the existing enum PostStatus
#Embeddable
#Data //lombok
#TypeDef(name = "pgsql_enum", typeClass = PostgreSQLEnumType.class)
#AllArgsConstructor //lombok
#NoArgsConstructor //lombok
public class PostStatus4Save {
#Enumerated(EnumType.STRING)
#Type(type = "pgsql_enum")
PostStatus postPermission;
}

Related

Relation XX does not exist; could not extract Resultset error while using a view convertHibernateAccessException

I am using a view in my entity class. Although the view-column mappings are exactly the same as in entity class, I am receiving the exception "ERROR: relation "location_view" does not exist - Position: 15 - underlying exception is SQLGrammarException could not extract ResultSet at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:261)"
When I replace the view to the underlying SQL query, it works in SpringBoot. Can you please let me know where I am going wrong?
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#Data
#ToString
#Entity
#Table(name = "location_view")
public class Location{
#Id
#Column(name = "id")
long id;
#Column(name = "name")
String name;
#Column(name = "total")
long total;
#Column(name = "created_by")
long createdBy;
#Column(name = "created_on")
Timestamp createdOn;
}
public interface LocationDAO extends JpaRepository<Location, Long> {
#Query(value = "select * from location_view", nativeQuery = true)
List<Location> getLocations();
}
In my controller, I am making call to locationDAO.getLocations();
Probably the table/view is in a different schema? Or maybe the user for the JDBC connection has no permission to read from that table/view?

Spring batch JdbcCursorItemReader : reading from tables having FK relation

Here's my Reader :
private static final String SELECT_ALL_BOOKS = "SELECT * FROM BOOKS WHERE COLOR = 'yellow'";
#Bean
public JdbcCursorItemReader<BookEntity> itemReader(final DataSource dataSource) {
return new JdbcCursorItemReaderBuilder<BookEntity>()
.name("book_reader")
.sql(SELECT_ALL_BOOKS)
.dataSource(dataSource)
.rowMapper(new BeanPropertyRowMapper<>(BookEntity.class))
.build();
}
And my entity :
#Entity
#Getter
#Setter
#Table(name = "book")
#AllArgsConstructor
#NoArgsConstructor
public class BookEntity implements java.io.Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id_book")
private Integer idBook;
#Column(name = "color")
private String color;
#Column(name = "page_number")
private Integer pageNumber;
#Column(name = "read")
private Boolean read;
#ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
#JoinColumn(name = "id_author")
private Author author;
...
...
}
Problem is : with my job executing my step, I'm having the books but with an author = null. So the foreign key is not mapped correctly, all the other String/Integer/Boolean fields are retrieved correctly.
I'm new with Spring batch so maybe I'm using a wrong kind of reader.
Any one has an idea about the problem ? Thanks
Please refer this- You are using JDBC Item reader that is mapped to native columns and properties are binded by BeanPropertyRowMapper
https://docs.spring.io/spring-batch/docs/current/reference/html/readersAndWriters.html#JdbcCursorItemReader
Change the query join with AUTHOR tables as a native query or use JPA readers to support ORM
Below reference will give repository reader
https://docs.spring.io/spring-batch/docs/current/api/org/springframework/batch/item/data/RepositoryItemReader.html
Below example give some idea to implement and its SO references
https://github.com/gpassini/Spring-Batch-RepositoryItemReader-NativeQuery-Example/tree/master/src/main

How to retrieve nested rest data resources generated by #RepositoryRestResource annotation?

I have to entities exposed by spring boot application powered by Spring data REST.
#Entity
#Table(name = "joke")
#Data
public class Joke {
#Id
#Column(name = "joke_id")
private Long id;
#Column(name = "content")
private String content;
#JsonProperty("category")
#JoinColumn(name = "category_fk")
#ManyToOne(fetch = FetchType.EAGER)
private Category category;
}
and category
#Entity
#Table(name = "category")
#Data
public class Category {
#Id
#Column(name = "category_id")
private int id;
#Column(name = "name")
private String name;
}
It is working fine and exposing the HAL+Json format. I'm using Traverson client which is working fine:
Traverson client = new Traverson(URI.create("http://localhost:8080/api/"),
MediaTypes.HAL_JSON);
HashMap<String, Object> parameters = Maps.newHashMap();
parameters.put("size", "2");
PagedModel<JokesDTO> jokes = client
.follow("jokes")
.withTemplateParameters(parameters)
.toObject(new PagedModelType<JokesDTO>() {
});
return jokes;
where JokesDTO is:
#Builder(toBuilder = true)
#Value
#JsonDeserialize(builder = JokesDTO.JokesDTOBuilder.class)
#JsonInclude(Include.NON_NULL)
public class JokesDTO {
private String content;
#JsonPOJOBuilder(withPrefix = "")
#JsonIgnoreProperties(ignoreUnknown = true)
public static class JokesDTOBuilder {
}
}
I'm new in HAL and HateOS and I would like to achieve 2 things (and question is - is it possible, and how):
Base on Traverson client call, how to retrieve category (or link to category) in one call? How to extend what I wrote. And I'm not talking about adding additional #JsonProperty annotation to my class definition.
Is it possible to expose the inner query from Spring data REST, so I would be able to get all data with one call, is it possible with #RepositoryRestResource?

Repository findIn confusion

My database has an Exchanges class which contains a list of CurrencyPairs.
Is it possible to use to use a Repository method to directly obtain a CurrencyPair which matches on name within a given Exchange? I'm thinking of something like
CurrencyPairDbo findByExchangeNameAndCurrencyPairIn(...)
but I can't see quite how to tie it all together. Or do I need to write a custom query for this? And does this need to be in the ExchangeRepository or the CurrencyPairRespository?
#Entity()
#Table(name = "Exchanges")
public class ExchangeDbo {
#Id #GeneratedValue
#Getter private Long id;
#Getter private String exchangeName;
#OneToMany(mappedBy = "exchange",
cascade = CascadeType.ALL,
orphanRemoval = true,
fetch = FetchType.EAGER)
#BatchSize(size=100)
#Getter private List<CurrencyPairDbo> listCurrencyPair = new ArrayList<>();
...
}
#Entity()
public class CurrencyPairDbo {
#Id #GeneratedValue
#Getter private Long id;
#Column(unique=true)
private String currencyPair;
#ManyToOne(fetch=FetchType.EAGER)
#Getter private ExchangeDbo exchange;
...
}
Edit:
I'm thinking it's not Find...In that I want at all. I think that something like:
List<CurrencyPairDbo> x = exchangeRepository.findByExchangeNameLowercaseAndListCurrencyPairCurrencyPair(exchangeName.toLowerCase(), currencyPair);
might work, except that in returns an Exchange object and a:
org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [biz.ianw.coindatabase.database.ExchangeDbo] to type [biz.ianw.coindatabase.database.CurrencyPairDbo]
This, in the currency pair repository, seems to do the job.
I added a lower case field for matching purposes and an index for efficiency.
CurrencyPairDbo findByExchangeExchangeNameLowercaseAndCurrencyPairNameLowercase( String exchangeName, String currencyPair );

JPA OneToOne not working

I followed by tutorial : http://www.codejava.net/frameworks/hibernate/hibernate-one-to-one-mapping-with-foreign-key-annotations-example
I have following code:
#Entity
#Table(name = DomainConstant.TABLE_USER)
public class User{
#Id
#Column(name = DomainConstant.DOMAIN_USER_ID)
#GeneratedValue
private Long userId;
private UserActivationCode userActivationCode;
///////////////////// CONSTRUCTOR....
/// STANDARD GET AND SET....
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = DomainConstant.DOMAIN_ACTIVATION_LINK_ID)
public UserActivationCode getUserActivationCode() {
return userActivationCode;
}
}
#Entity
#Table(name = DomainConstant.TABLE_USER_ACTIVATON_LINK)
public class UserActivationCode {
#Id
#Column(name = DomainConstant.DOMAIN_ACTIVATION_LINK_ID)
#GeneratedValue
private Long userActivationCodeId;
#Column(name = DomainConstant.DOMAIN_ACTIVATION_DATE)
#Temporal(javax.persistence.TemporalType.DATE)
private Date date;
#Column(name = DomainConstant.DOMAIN_ACTIVATION_CODE)
private String code;
///////////////////// CONSTRUCTOR....
/// STANDARD GET AND SET....
}
When I save the User object it does not make record in UserActivationCode, why?
Like this:
User newUser = new User();
newUser.setUserActivationCode(new UserActivationCode("this is example"));
userDao.save(newUser);
I have record only in user table.
Can you tell me why?
Your problem is that you are mixing access types. In the User entity you have specified #Id on a field (private Long userId) whereas you have defined the join mapping on a property (the getter to UserActivationCode). If you specify the join mapping on the field, it should work as is.
#Entity
#Table(name = DomainConstant.TABLE_USER)
public class User{
#Id
#Column(name = DomainConstant.DOMAIN_USER_ID)
#GeneratedValue
private Long userId;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = DomainConstant.DOMAIN_ACTIVATION_LINK_ID)
private UserActivationCode userActivationCode;
///////////////////// CONSTRUCTOR....
/// STANDARD GET AND SET....
public UserActivationCode getUserActivationCode() {
return userActivationCode;
}
}
For more information on access and access types, see Access, Java EE 7