I have a Class whose objects I want to be able to persist via Hibernate such as:
package my.package
#Entity
#Table(name="hibernatedclass")
public class HibernatedClass {
#Id
#GeneratedValue(strategy= GenerationType.AUTO)
private Long id;
#Column(name="firstname")
private String firstname;
[....]
}
As it can be seen the name I have given the table to store the objects of my.package.HibernatedClass is named hibernatedclass.
What I am looking for in an answer is: How can this naming be automatized?
Something that would imho look similar to this pseudo-code.
#Table(name=class.getCanonicalName())
Related
I have an entity EncodingResult that references three others. I want to find out how to use the repository's findBy() methods to return an entity based on its foreignKey so that I can, for example, make a GET request passing a Video's foreign key as a parameter and return whether or not there is an EncodingResult containing a Video with the given foreignKey.
How would you go about doing this? I tried reading a bit on EntityGraphs and was rather confused. There also doesn't seem to be a great number of content explaining these parts of the framework.
It would be better if you posted the code for your entities, but from your description, I think you have something like this:
#Entity
public class EncodingResult {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#OneToMany(mappedBy = "encodingResult")
private List<Video> videos=new ArrayList<Video>();
//...boilerplate
}
#Entity
public class Video {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
#ManyToOne
EncodingResult encodingResult;
//...boilerplate
}
So you can define findBy methods in your EncodingResultRepository like so.
public interface EncodingResultRepository extends JpaRespository<EncodingResult, Integer> {
public Optional<EncodingResult> findByVideoName(String name);
public Optional<EncodingResult> findByVideoId(Integer id);
}
I have the following Pojo:
#Entity
#Table(name = "USER")
class User {
#Id
private long id;
private String name;
private int age;
private long lastVisited;
private long lastPlayed;
private long lastPayed;
...
}
I would like somehow if possible to map the Pojo like this:
#Entity
#Table(name = "USER")
class User {
#Id
private long id;
private String name;
private int age;
#Embedded
private UserStatistics statistics;
...
}
#Embeddable
class UserStatistics {
private long lastVisited;
private long lastPlayed;
private long lastPayed;
}
BUT, I DON'T want to move the statistics columns into a new
USER_STATISTICS table and do #OneToOne mapping.
Is there a Hibernate trick I can use here?
Thanks!
What you did is already enough, Hibernate does not require you to define fields for all columns in your table. It's rather the other way around - all non-transient fields should be reflected as columns in the corresponding table either using name defined in #Column annotation or generated using a naming convention used in hibernate configuration.
The example you presented is sufficient and will work, but I wouldn't recommend it as you can have two entities mapping single row at the same time.
I found similar questions, but they did not answer my question.
I have two entities with a many-to-one relationship - unidirectional.
But most importantly, the relationship is lazy. Because it is correct to use a lazy connection, everyone knows it.
Code:
#Entity
public class User implements BaseEntity {
#Id
#Column
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column
private String name;
#ManyToOne(fetch = FetchType.LAZY)
private City city;
}
#Entity
public class City implements BaseEntity {
#Id
#Column
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column
private String name;
}
interface BaseEntity {
void setId(Long id);
Long getId();
}
I wrote a method that allows you to search by the transferred fields of the entity.
An example of how this works:
public class Search<T extends BaseEntity> {
public List<T> getByFields(T entity, List<FieldHolder> data) {
// create criteria with passed field name and value by reflection
}
}
class FieldHolder {
private String fieldName;
private Object value;
/**
* "true" - means that the field "value" contains id related object
* "false" - elementary type like: String, Wrapper, Primitive
*/
private boolean isRelationId;
}
The problem is that problems start when you need to search and related objects - by creating related queries.
The following entry is used to send the associated field: "city.id" and the problem is that when I transfer the essence of the related object (City) it is in a proxy and I cannot get id by reflection from City.
My function works perfectly if you specify:
#ManyToOne(fetch = FetchType.EAGER)
private City city;
But it will greatly affect performance, since I have a lot of related objects. Therefore, I want to solve this problem for a lazy load.
I know that this is not an easy task. But perhaps there is some opportunity to somehow get around this problem.
Hibernate Mapping
How to implement such a code?
Each company has two properties, they are company name and estimated annual earnings.
There are two types of companies: 1- Main company, 2 - Subsidiary company.
The company can belong only to one company but can have a few child companies.
public class Company {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String companyName;
private double estimatedAnnualEarnings;
private Company company; // here need to do a #OneToOne
private List<Company> subsidiaryCompany; // here need to do a #OneToMany
}
In your Implementation you should use :
The #Entity annotation in your class level, so the entity can be persisted to database.
The #Column annotation with the companyName and estimatedAnnualEarnings properties, so they can be persisted as columns in the database.
#ManyToOne annotation with the company field, so it can be mapped with a self-reference relationship.
The same goes with the subsidiaryCompany List which needs to be mapped with #OneToMany annotation to have a relationship too.
This is how should be your code:
#Entity
public class Company {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column
private String companyName;
#Column
private double estimatedAnnualEarnings;
#ManyToOne(cascade={CascadeType.ALL})
#JoinColumn(name="mainCompanyId")
private Company mainCompany;
#OneToMany(mappedBy="mainCompany")
private List<Company> subsidiaryCompanies;
//getters and setters goes here
}
Note
I changed the name of company field to mainCompany and
subsidiaryCompaniy to subsidiaryCompanies for better readability
and to make it fit the logic better.
If you want to give your entity a different name in the database you
should use #Table(name="differentName") in the class level with
#Entity annotation, the smae thing with the columns you can add
name property to the #Column annotation i.e
#Column(name="company_name") if you want different names.
Quick hibernate question - How can I use Hibernate annotations to define this class as an entity -
public class NativeType {
private long id;
private String name;
private int maxPrecision;
private byte maxScale;
private DataStoreProvider provider;
linked as a Map Collection in the AbstractDataStoreProvider class -
public abstract class AbstractDataStoreProvider implements DataStoreProvider,
Serializable{
private Map<String, NativeType> uniqueNativeTypes;
..
public interface DataStoreProvider {
so I can store this in DB tables like so -
**datastore_provider**
provider_id | provider_name
**native_type**
native_type_id | name | max_precision | max_scale | provider_id
I think its me, but I cant navigate the Hibernate specs very easily. New to Java, and newer to JPA + Hibernate. Appreciate the guidance!
Code Sample
I think you can use the following -
#Entity
#Table(name = "native_type")
public class NativeType {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "native_type_id")
private Long id;
private String name;
#Column(name = "max_precision")
private int maxPrecision;
#Column(name = "max_scale")
private byte maxScale;
#ManyToOne
#JoinColumn(name="provider_id")
private DataStoreProvider provider;
// rest of the class (getter setter etc.)
}
ID Generation
I am assuming you are auto-generating your database ids, hence I marked it with the #GeneratedValue annotation. As for the strategy, I specified AUTO which is only suitable for local experiments. For production-grade application, you'll have to choose between SEQUENCE, IDENTITY, and TABLE.
Relation Mapping
I assumed that you are going to create a DataStoreProvider entity too. In that case, you can specify the relation between them as described above.
Reference
For further reference, you can consult this excellent book.