Which Polygon classes hibernate can accept? - spring

I have a Spring project and I'am trying to create a Polygon Object in Java that Hibernate can handle but I have seen that it exists in Java many class to create a Polygon Object like "org.geojson.Polygon", "com.vividsolutions.jts.geom.Polygon" or "org.springframework.data.geo.Polygon". How can I know which of this classes Hibernate accepts ?
My class :
#Entity public class Area implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long idArea;
#Column( columnDefinition = "Polygon" )
private Polygon coordinates; // What imports to do for this Polygon attribute?
#Column(unique = true)
private String name;
}
// Constructors and getters/setters ...
Thanks for any help !

Out of the box Hibernate-core only supports a relatively limited number of types, if you want to use complex types such as Polygon you'll need to either map them yourself (implementing org.hibernate.UserType or org.hibernate.CompositeUserType) or use a library that does it for you.
For spatial data there's the hibernate-spatial, you'll find an introduction here but essentially you'll need to add the dependency:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-spatial</artifactId>
<version>${hibernate.version}</version>
</dependency>

Related

How to Spring Cache JPA nested Objects?

Have Domain Object that has a series of Nested Objects thus. B and C are reference Data Objects. The values are static data that we never update in the table - ever.
Class A {
B b;
C c;
}
class B {
}
class C {
}
B, C etc are quite "heavy" and take some time to return from the DB.
I have a repository written thus:
class MyRepository extends CrudRepository<A, Long> {
}
I need a way to cache B, C so they are not queried everytime whenever I do this. Currently everytime I lookup A both B and C are retrieved from the DB even though they are static data:
MyRepository.findById(1L)
I KNOW I can use Spring Cache at the Service level. But what I'm interested in is DATABASE level Cache. B, C etc are using in many different places and more to come (including PUT/POST) so they all can make best use of database level caching of these reference data since using Spring Cache : Save operations dont get much benefits.
Please check if it is what you want.
maven add
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>5.2.2.Final</version>
</dependency>
application.properies add
hibernate.cache.use_second_level_cache=true
hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory
entity modify
#Entity
#Cacheable
#org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Foo {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "ID")
private long id;
#Column(name = "NAME")
private String name;
// getters and setters
}
https://www.baeldung.com/hibernate-second-level-cache

How di I turn my class into an Entity in Room Persistence?

This is my first time using Room Persistence Library and I am having difficulties understanding the concept of entity.
So I have these two classes:
public class CapturedTime
{
#SerializedName("startTime")
#Expose
private Long startTime;
#SerializedName("endTime")
#Expose
private Long endTime;}
and
public class CapturedItem implements Parcelable {
private String serialNumber;
private CapturedTime firstCapturedTime;
private CapturedTime secondCapturedTime;}
I believe it's pretty straightforward for the CapturedTime class but I have no idea what I should do for the CapturedItem class. Can I just make the CapturedTime variables into columns or are there steps that I should do first?
First add dependency in buid.gradle file
dependencies {
def room_version = "2.1.0-rc01"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version" // For Kotlin use kapt instead of annotationProcessor
}
After that use #Entity annotation to declare normal POJO class as entity in Room persistence library.
#Entity(tableName = "your_table_name")
public class CapturedTime{
#SerializedName("startTime")
#Expose
#ColumnInfo(name = "start_time")
private long startTime;
#SerializedName("endTime")
#Expose
#ColumnInfo(name = "end_time")
private long endTime;
}
#ColumnInfo used to declare column name in table, by default column name is variable name if you do't provide #ColumnInfo annotation
If you want to store custom object in room you use
#TypeConverters() annotation
In your case,
#TypeConverters(CapturedTime.class)
private CapturedTime firstCapturedTime;
For more information please visit this

Service cannot auto-wire in Entity class

I needed a RoleMappingService class(which is annotated by #Service) object into a Employee class (which is annotated by #Entity)
below are my classes
********************* RoleMappingsService class **********************
#Service
public class RoleMappingsService {
#Autowired
RolesMappingDao rolesMappingDao;
public List<RolesMappings> getRolesMappingByauthSystemRole(String authSystemRole) {
return rolesMappingDao.getRolesMappingByauthSystemRole(authSystemRole);
}
}
############### Employee class
#Configurable
#Component
#Entity
#NamedQuery(name = "Employee.findAll", query = "SELECT e FROM Employee e")
public class Employee implements Serializable, UserDetails {
#Autowired
#Transient
RoleMappingsService roleMappingsService;
public static final String STATUS_ACTIVE = "ACTIVE";
public static final String STATUS_INACTIVE = "INACTIVE";
public static final String STATUS_LOCKED = "LOCKED";
public static final String STATUS_ONLEAVE = "ONLEAVE";
public static final String STATUS_EXPIRED = "EXPIRED";
private static final long serialVersionUID = 1L;
#Id
#Column(name = "emp_id")
private String empId;
#Column(name = "emp_password")
private String empPassword;
#Column(name = "emp_email")
private String empEmail;
#Column(name = "emp_address")
private String empAddress;
#Column(name = "emp_age")
private int empAge;
#Column(name = "emp_firstname")
private String empFirstname;
}
Here Autowire is not working for roleMappingsService and the object is always found null. However I tried to autowire same object in some other service and there Autowire is perfectly working.
( I know Entity class is only used for representing database table but in my case I need to set some field values which depend on another table so need to fetch data using service)
JB Nizet is totally right
I'll try to provide more explanations here.
Spring can Autowire only beans, objects that it manages, and not arbitrary objects.
Entities are usually created from within a JPA (Hibernate) and are not something that you want to manage by Spring.
There is a related discussion available here but bottom line you should never do something like this.
Why not?
Here are a couple of questions/reasons:
Maybe these entities will go outside spring context at all (serialization), what should that reference contain? Should we also serialize the service? How?
What will happen if the method that turns to the service will be called "outside" the spring driven application (maybe even in different JVM)?
If there are, say 1000 objects returned by that query, do you really want all of them to reside in application context? Or maybe should they be of "prototype" scope?
As you see, it doesn't play nice with spring concepts. I think the reason for it is that Hibernate and JPA do not "support" an idea of methods inside entities, it's just a different framework. I know there are other frameworks that do allow such a concept, but Hibernate/JPA just doesn't, period
So instead of trying to inject the service into the entity bean, probably you should redesign the application so that the service method will be called from outside, maybe via some facade, and entities will be just populated by query, and then "enriched" with additional information if we're talking about SELECT queries, or, alternatively, some information should be pre-set on entity objects, generated by the Business Logic Layer and only then the entity object should be stored in DB

Using Spring JPA Projection with JHipster

I'm having some difficulties to use Spring Data JPA Projections in a project generated with JHipster version 4.14.5.
I'm following Spring's orientation on how to make projections using JPA respositories, however I'm not having any success. The repo give me null values when I try to use projections.
Since I'm not a big connoisseur of JHipster's pipes, I hope somebody out there may help me out.
My Entity
#Entity
#Table(name = "research")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Research implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotNull
#Column(name = "answer", nullable = false)
private String answer;
#OneToOne(optional = false)
#NotNull
#JoinColumn()
private Question question;
// getters and setters
Entity projection:
public interface ResearchSimple {
Long getId();
String getAnswer();
}
Entity's repo:
#Repository
public interface ResearchRepository
extends JpaRepository<Research, Long> {
#Query("SELECT r FROM Research r)
List<ResearchSimple> findAllAsSimple();
}
Test Results
List<ResearchSimple> result = repo.findAllAsSimple();
assertEquals(result.size, dbSize); // OK
ResearchSimple simple = result.get(0);
assertNotNull(simple); // OK
assertNotNull(simple.getId); // FAIL!
assertNotNull(simple.getAnswer); // FAIL!
Debugging the value obtained in simple I've noticed that the projection was made, but I can't access it's value. Notice that the class br.com.pixinside.projection.ResearchSimple is present in simple's advised.
org.springframework.aop.framework.ProxyFactory: 2 interfaces [br.com.pixinside.projection.ResearchSimple, org.springframework.data.projection.TargetAware]; 3 advisors [org.springframework.aop.support.DefaultPointcutAdvisor: pointcut [Pointcut.TRUE]; advice [org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor#1d62a0b], org.springframework.aop.support.DefaultPointcutAdvisor: pointcut [Pointcut.TRUE]; advice [org.springframework.data.projection.ProxyProjectionFactory$TargetAwareMethodInterceptor#3b89f41a], org.springframework.aop.support.DefaultPointcutAdvisor: pointcut [Pointcut.TRUE]; advice [org.springframework.data.projection.ProjectingMethodInterceptor#198453c9]]; targetSource [SingletonTargetSource for target object [org.springframework.data.jpa.repository.query.AbstractJpaQuery$TupleConverter$TupleBackedMap#319267ad]]; proxyTargetClass=false; optimize=false; opaque=true; exposeProxy=false; frozen=false
if you wanna use projection with manually queries , then you should use aliases that matches field names in your projection interface. #Query("SELECT r.id as id, r.answer as answer FROM Research r)
Or just skip #Query, and use List<ResearchSimple> findAllSimplifiedBy();

How to map user data type in cassandra using spring boot data

I am looking out for some help related with spring boot data using Cassandra database.
I have following dependencies in my pom.xml.
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-boot-starter-data-cassandra</artifactId>
</dependency>
<dependency>
<groupId>com.datastax.cassandra</groupId>
<artifactId>cassandra-driver-core</artifactId>
<version>2.1.10.3</version>
</dependency>
<dependency>
<groupId>com.datastax.cassandra</groupId>
<artifactId>cassandra-driver-mapping</artifactId>
<version>2.1.10.3</version>
</dependency>
The table structure looks like:
#Table(value = "TEST_ORDERS")
public class OrderDTO {
#PrimaryKey
#Column(value = "email")
private String emailId;
#Column(value = "order_id")
private int orderId;
#Column(value = "creation_date")
private Timestamp creationDate;
#Column(value = "discount_total")
private double discountTotal;
#Column(name = "shipments")
//This is a UDT type
private Set<ShippingDetails> shipments;
//getters and setters here
}
The ShippingDetails object is a UDT with following declartion and i defined as a frozen collection in the cassandra CQL sripts
#UDT(name = "shipping", keyspace = "mc_checkout")
public class ShippingDetails {
#Field(name = "name")
private FullName name;
#Field(name = "quantity_shipped")
private int quantityShipped;
#Field(name = "shipping_address")
private CheckoutAddress shippingAddress;
//so on
}
There is a repository created for the basic CRUD operations:
#Repository
public interface OrderRepository extends CrudRepository<OrderDTO, String> {
}
When i try to invoke findOne API of this repository in my Service class
i get below error:
Cassandra entities must have the #Table, #Persistent or #PrimaryKeyClass Annotation
Spring Data for Apache Cassandra and Datastax' Mapping are two independent tools that try to accomplish the same. Please use either one but don't mix these.
CrudRepository is a Spring Data type while #Field and #UDT are coming from Datastax Mapping.
UDT support for Spring Data for Apache Cassandra is available as of version 1.5, see reference docs. Spring Data for Apache Cassandra 1.5 requires Datastax Java Driver 3.0 or newer.

Resources