i have base entity like
#MappedSuperclass
public class BaseEntityCore implements Serializable {
#CreatedBy
#Column(name = "olusturan", /* nullable = false, */ length = 50, updatable = false)
private String createdBy;
#CreatedDate
//#NotNull
#Column(name = "olusturma_tarihi", nullable = false, updatable = false)
private LocalDateTime createdDate ;
#LastModifiedBy
#Column(name = "guncelleyen", length = 50)
private String lastModifiedBy;
#LastModifiedDate
#Column(name = "guncelleme_tarihi")
private LocalDateTime lastModifiedDate;
#Column(name = "aktif")
private int aktif;
// getter and setter
and a entity extends this base entity like
#Entity
#Table(name = "foo")
#EntityListeners(value = { AbstractEntityListenerCore.class })
public class foo extends BaseEntityCore {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name="foo_name")
private String fooName;
//getter and setter
}
with spring , spring jpa. i also have entity repo like
public interface FooRepository extends JpaRepository<Foo, Long> {
Optional<Foo> findByFooName(String name);
}
now i can save entity with foo.setAktif(1). after saving foo i see on table aktif is 1. After that i run findByFooName method. this turns the object but this object has 2 aktif properties. first is aktif and value is 1 and the other is BaseEntityCore.aktif and value is 0. i check with if clause like
if(foo.getAktif()==1){
//do something
}
else {
//throws exception;
}
i cant get it why always throws exception.
You don't need your if else clause.
Just search always for Entities with "Aktif" == 1.
So extend your repo class with an other method
Optional<Foo> findByFooNameAndAktif(String name, int aktif);
and only search for the "aktif" you want.
But your question is about the 2 properties of "Aktif" right?
We have structure something like bellow:
#MappedSuperclass
public abstract class BaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private Long id;
#Override
public boolean equals(Object o) {
if (this == o) return true;
BaseEntity that = (BaseEntity) o;
if (getId() != null ? !getId().equals(that.getId()) : that.getId() != null) {
return false;
}
return true;
}
#Override
public int hashCode() {
return Objects.hash(getId());
}
}
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#Table(name = "BASE_ORGANIZATION")
#DiscriminatorColumn(name = "disc")
#DiscriminatorValue("baseOrganization")
public class BaseOrganization extends BaseEntity {
#Column(name = "TITLE")
private String title;
}
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#Table(name = "BASE_PERSONNEL")
#DiscriminatorColumn(name = "disc")
#DiscriminatorValue("basePersonnel")
public class BasePersonnel extends BaseEntity {
#Column(name = "FIRSTNAME")
private String firstName;
#Column(name = "LASTNAME")
private String lastName;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "BASE_ORGANIZATION_ID")
private BaseOrganization baseOrganization;
}
BaseEntity, BasePersonnel and BaseOrganization is in core_project that all projects can used these objects. Now we create a project that depended to core_project. We must to extends BasePeronnel and BaseOrganization based on our business context. For this reason we added some classes in our project like bellow:
#Entity
#DiscriminatorValue("organization")
public class Organization extends BaseOrganization {
#Column(name = "MISSION_Type")
private String missionType;
}
#Entity
#DiscriminatorValue("personnel")
public class Personnel extends BasePersonnel {
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "MISSION_ORGANIZATION_ID")
private Organization missionOrganization;
}
Our problem is raised, when we wanna to get all personnel. When we called getAllPersonnel method in PersonnelRepository, hibernate logged bellow message:
WARN o.h.e.i.StatefulPersistenceContext - HHH000179: Narrowing proxy to class org.xyz.organization.Organization - this operation breaks ==
After that, when we see List<Personnel> object, missionOrganization property is null, but baseOrganization property in super class is loaded!
We think when tow class that have SINGLE_TABLE inheritance strategy, hibernate LazyInitializer can not detect correct concrete class.
Also we debugged narrowProxy method in StatefulPersistenceContext class and we understood that concreteProxyClass.isInstance(proxy) returned false. because proxy object have BaseOrganization object in LazyInitializer and concreteProxyClass refer to Organization class!
I have spring boot application which use spring data and hibernate to fetch and insert data to database.
I have one-to-many table relation:
#Entity
#Data
#EqualsAndHashCode(of = { "id" })
#Table(name = "direction")
public class Direction {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private Long id;
#Column(name = "name")
private String name;
}
and
#Entity
#Table(name = "subdivision")
#Data
#EqualsAndHashCode()
public class Subdivision {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false)
private Long id;
#Column(name = "name")
private String name;
#ManyToOne()
#JoinColumn(name = "direction_id", referencedColumnName = "id")
private Direction direction;
}
I have lombok plugin for boilarplate code generation.
I also have repository
public interface SubdivisionRepository extends CrudRepository<Subdivision, Long> {
List<Subdivision> findAll();
List<Subdivision> findByDirection(Direction direction);
}
and service
#Service
public class SubdivisionServiceImpl implements SubdivisionService {
#Autowired
private SubdivisionRepository subdivisionRepository;
#Override
public List<Subdivision> findAll() {
return subdivisionRepository.findAll();
}
#Override
public Subdivision findById(Long id) {
return subdivisionRepository.findById(id).get();
}
#Override
#Transactional
public void save(Subdivision subdivision) {
subdivisionRepository.save(subdivision);
}
#Override
public List<Subdivision> findByDirection(Direction direction) {
return subdivisionRepository.findByDirection(direction);
}
}
That's all. Then I try to update subdirection by changing direction type it shows hibernate exception: Error during managed flush [org.hibernate.HibernateException: identifier of an instance of com.entity.Direction was altered from 2 to 3]
I found the same question on stackoverflow but nothing suggested helped.
I tried to change fetch type and cascade type but it didn't helped.
Does anyone have solution?
P.S Here the code how I update entity
public void updateSubdivision(Subdivision subdivision){
Direction d = directionService.findById(subdivision.getDirection().getId());
Subdivision s = new Subdivision();
s.setDirection(d);
s.setName(subdivision.getName());
s.setId(subdivision.getId());
subdivisionService.save(s);
}
It's controller method
I know how to implement spring data repositories,
Create an interface like this :
public interface CountryRepository extends CrudRepository<Country, Long> {}
Now Country is an AbstractCatalog and I have (a lot) more catalogs in my project.
I'm wondering if I can make only one repository that would work for all the catalogs:
public interface AbstractCatalogRepository extends CrudRepository<AbstractCatalog, Long> {}
Now I don't see a problem while saving, but if I want to search an AbstractCatalog I'm already sure that I'll hit the wall because the repository will not know which sub-class it must choose.
AbstractCatalog.class
#MappedSuperclass
public abstract class AbstractCatalog extends PersistentEntity {
/**
* The Constant serialVersionUID.
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
/**
* The code.
*/
#Column(unique = true, nullable = false, updatable = false)
private String code;
/**
* The description.
*/
#Column(nullable = false)
private String description;
/**
* The in use.
*/
#Column(name = "IN_USE", nullable = false, columnDefinition = "bit default 1")
private Boolean inUse = Boolean.TRUE;
// getters and setters
}
Country.class
#Entity
#Table(name = "tc_country")
#AttributeOverrides({
#AttributeOverride(name = "id", column =
#Column(name = "COUNTRY_SID")),
#AttributeOverride(name = "code", column =
#Column(name = "COUNTRY_CODE")),
#AttributeOverride(name = "description", column =
#Column(name = "COUNTRY_DESCRIPTION"))})
public class Country extends AbstractCatalog {
public static final int MAX_CODE_LENGTH = 11;
#Column(name = "GEONAMEID", nullable = true, unique = false)
private Long geonameid;
// getter and setter
}
Has anyone any idea, how I could use only ONE repository for all the implementations of AbstractCatalog class without having to create the same interface over and over again with minimal differences in name and other properties?
If you aren't using table inheritance on the database side (e.g. super class table with descriminator column), AFAIK, and based off reading the JPA tutorial, this can't be done (i.e. simply using #MappedSuperclass annotation for your abstract class)
Mapped superclasses cannot be queried and cannot be used in EntityManager or Query operations. You must use entity subclasses of the mapped superclass in EntityManager or Query operations. Mapped superclasses can't be targets of entity relationships
Note, the JPA repository abstraction uses an EntityManager under the hood. I did a simple test, and what you will get (in the case of Hibernate implementation) an "IllegalArgumentException : not an entity AbstractClass"
On the other hand, if you do use table inheritance, then you can use the abstract type. I know you said "with just the minimal change" (and I guess my short answer is I don't think it's possible - probably for the reasons you guessed), so I guess the rest of this answer is for other inquiring minds ;-)
An example of a table inheritance strategy would be something like this (disclaimer: this is not the correct visualization for erd inheritance, but MySQL Workbench doesn't support it, but what I have below forward engineered the model to MYSQL the way it needs to be)
Where CountryCatalog has a FK/PK reference to the AbstractCatalog table pk (id). The AbstractCatalog table has a descriminatorColumn that will be used to determine to which subtype the supertype occurrence is related.
In terms of how you would code that, it would look something like
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
#DiscriminatorColumn(name="descriminatorColumn")
#Table(name="AbstractCatalog")
public abstract class AbstractCatalog {
#Id
private long id;
...
}
#Entity
#Table(name = "CountryCatalog")
public class CountryCatalog extends AbstractCatalog {
// id is inherited
...
}
public interface AbstractCatalogRepository
extends JpaRepository<AbstractCatalog, Long> {
}
#Repository
public class CountryCatalogServiceImpl implements CountryCatalogService {
#Autowired
private AbstractCatalogRepository catalogRepository;
#Override
public List<CountryCatalog> findAll() {
return (List<CountryCatalog>)(List<?>)catalogRepository.findAll();
}
#Override
public CountryCatalog findOne(long id) {
return (CountryCatalog)catalogRepository.findOne(id);
}
}
Basically, in conclusion, what you are trying to do won't work if you don't have table inheritance. The class type for the repository needs to be an entity. If your tables aren't set up this way for inheritance, it just comes down to whether or not you want to change the tables. It may be a bit much just to avoid multiple repositories though.
Some references I used are here and here
Note: Everything in this answer is tested against Hibernate provider
Oke, new project and I'm following this set up a little bit.
The problem was :
We want to add attachments, but an attachment can be uploading a file, a link or a mail.
Pojo classes :
Attachment.java :
#Entity
#Table(name = "T_ATTACHMENT")
#Inheritance(strategy = InheritanceType.JOINED)
#DiscriminatorColumn(name = "DISCRIMINATOR", discriminatorType = DiscriminatorType.STRING)
public abstract class Attachment {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "ATTACHMENT_SID")
private Long id;
#ManyToOne
#JoinColumn(name = "TASK_SID", referencedColumnName = "TASK_SID", nullable = false, unique = false, insertable = true, updatable = true)
private Task task;
#ManyToOne
#JoinColumn(name = "USER_SID", referencedColumnName = "USER_SID", nullable = false, unique = false, insertable = true, updatable = true)
private User user;
public Task getTask() {
return task;
}
public void setTask(Task task) {
this.task = task;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
FileAttachment.java :
#Entity
#Table(name = "T_FILE_ATTACHMENT")
#DiscriminatorValue("FILE")
public class FileAttachment extends Attachment {
#Column(name = "NAME", nullable = false, unique = false)
private String fileName;
#Lob
#Basic
#Column(name = "FILE", nullable = false, unique = false)
private byte[] file;
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public byte[] getFile() {
return file;
}
public void setFile(byte[] file) {
this.file = file;
}
}
MailAttachment.java :
#Entity
#Table(name = "T_MAIL_ATTACHMENT")
#DiscriminatorValue("MAIL")
public class MailAttachment extends Attachment {
#Column(name = "RECIPIENT", nullable = false, unique = false)
private String to;
#Column(name = "CC", nullable = true, unique = false)
private String cc;
#Column(name = "BCC", nullable = true, unique = false)
private String bcc;
#Column(name = "TITLE", nullable = true, unique = false)
private String title;
#Column(name = "MESSAGE", nullable = true, unique = false)
private String message;
public String getTo() {
return to;
}
public void setTo(String to) {
this.to = to;
}
public String getCc() {
return cc;
}
public void setCc(String cc) {
this.cc = cc;
}
public String getBcc() {
return bcc;
}
public void setBcc(String bcc) {
this.bcc = bcc;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
LinkAttachment.java :
#Entity
#Table(name = "T_LINK_ATTACHMENT")
#DiscriminatorValue("LINK")
public class LinkAttachment extends Attachment {
#Column(name = "DESCRIPTION", nullable = true, unique = false)
private String description;
#Column(name = "LINK", nullable = false, unique = false)
private String link;
public String getDescription() {
return description == null ? getLink() : description;
}
public void setDescription(String description) {
this.description = description;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
}
Spring data repo's :
AttachmentRepository.java:
public interface AttachmentRepository extends CustomRepository<Attachment, Long> {
List<Attachment> findByTask(Task task);
}
CustomRepository.java :
public interface CustomRepository<E, PK extends Serializable> extends
PagingAndSortingRepository<E, PK>,
JpaSpecificationExecutor<E>,
QueryDslPredicateExecutor<E> {
#Override
List<E> findAll();
}
And at last the service :
#Service
public class AttachmentServiceImpl implements AttachmentService {
#Inject
private AttachmentRepository attachmentRepository;
#Override
public List<Attachment> findByTask(Task task) {
return attachmentRepository.findByTask(task);
}
#Override
#Transactional
public Attachment save(Attachment attachment) {
return attachmentRepository.save(attachment);
}
}
This results in :
I can save to the abstract repo with any implementation I created, JPA will do it correct.
If I call findByTask(Task task) I get a List<Attachment> of all the subclasses, and they have the correct subclass in the back.
This means, you can make a renderer who do instanceof and you can customize your rendering for each subclass.
Downside is, you still need to create custom specific repository's, but only when you want to query on a specific property what is in the subclass or when you only want 1 specific implementation in stead of all implementations.
What DB are you using?
If it's JPA, take a look at
Can I use a generic Repository for all children of a MappedSuperClass with Spring Data JPA?
If it's Mongo you need to properly tune Jackson polymorphism configuration
http://wiki.fasterxml.com/JacksonPolymorphicDeserialization
So this is possible.
I have the following
#Entity
#Table(name = "PROJECTS")
public class Project implements Serializable {
#Id
private Integer SlNo;
#Id
private Long projectNo;
private Date projectDate;
}
and in DAO class
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Long> countQ = cb.createQuery(Long.class);
Root<Project> empCount = countQ.from(Project.class);
countQ.select(cb.count(empCount));
TypedQuery<Long> countquery = entityManager.createQuery(countQ);// error in this line
I am getting exception java.lang.IllegalStateException: No supertype found in the above line. How can I resolve or workaround this issue? Looks like there is a bug, are there any solution to this?
I am using Hibernate 4.1.0.Final
I have resolved the issue by using #EmbeddedId in Entity class and #Embeddable in Primary Key class.
#Entity
#Table(name = "PROJECTS")
public class Project {
#Column(name = "SL_NO" , insertable = false, updatable = false)
private Integer SlNo;
#Column(name = "PROJECT_NO" , insertable = false, updatable = false)
private Long projectNo;
private Date projectDate;
#EmbeddedId
ProjectPK projectPK;
and Primary Key class
#Embeddable
public class ProjectPK implements Serializable {
#Column(name = "SL_NO")
private Integer SlNo;
#Column(name = "PROJECT_NO")
private Long projectNo;
//with hashCode and equals implementation
for the case Using #EmbeddedId, here is my solution. This code I have written in one class itself, in Entity class.
Class MyEntity - It is my actual Entity class for my table. "OtherFields" are those fields which are not part of primary key.
Class MyEntityPrimaryKeys - It is the class made for my composite key which makes a primary key for my "MyEntity" class. Here ROLLNO and AGE together makes a primary key.
MyEntity.java
#Entity
#Table(name = "myTable")
public class MyEntity extends GenericPersistableEntity implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
MyEntityPrimaryKeys id;//Composite Primary key
//Composite fields can be declared here for getter and setters
#Column(name = "ROLLNO")
private Long RollNo;
//Composite fields can be declared here for getter and setters
#Column(name = "AGE")
private Long age;
#Column(name = "OtherFields"
private Long OtherFields;
//getter and setters comes here
}
#Embeddable
class MyEntityPrimaryKeys implements Serializable{
private static final long serialVersionUID = 1L;
#Column(name = "ROLLNO")
Long RollNo;
#Column(name = "AGE")
Long age;
#Override
public int hashCode() {
HashCodeBuilder hcb = new HashCodeBuilder();
hcb.append(RollNo);
hcb.append(age);
return hcb.toHashCode();
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof MyEntityPrimaryKeys)) {
return false;
}
MyEntityPrimaryKeys that = (MyEntityPrimaryKeys) obj;
EqualsBuilder eb = new EqualsBuilder();
eb.append(RollNo, that.RollNo);
eb.append(age, that.age);
eb.append(tonMonth, that.tonMonth);
eb.append(tonYear, that.tonYear);
return eb.isEquals();
}
}