I know I need to implement Serializable in the classes which neet to be set to the Clipboard. But for the Objects with objects as attributes in them, do I need to implement Serializable on all the object attributes. And does it follow that I need to implement Serializable in the Objects within object attributes?
For example
TestObject implements Serializable
{
private Object o = new Object();
}
Object o implements Serializable
{
private AnotherObject ao = new AnotherObject()
}
does "AnotherObject" have to be serializable too?
Yes every object you want to serialize should implement Serializable (even though it is part of another serializable object)
Related
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
I am trying to migrate our project to use Room, which, by the way, I think is an awesome step forward.
I have the following structure:
public class Entity extends BaseObservable {
#PrimaryKey(autoGenerate = true)
#ColumnInfo(name = "_id", typeAffinity = ColumnInfo.INTEGER)
private long mId;
#ColumnInfo(name = "is_dirty")
#TypeConverters(BooleanTypeConverter.class)
private boolean mIsDirty;
// default constructor and accessors omitted for brevity
}
#Entity(tableName = "some_entities")
public class SomeEntity extends Entity {
#ColumnInfo(name = "type", typeAffinity = ColumnInfo.TEXT)
private String mType;
#ColumnInfo(name = "timestamp", typeAffinity = ColumnInfo.INTEGER)
private long mTimestamp;
// constructor, accessors
}
When I try to compile my project, it fails with no specific error.
If I try to compile it with a flat entity hierarchy, all is well.
So, my main question is:
Does Room support entity inheritance? Will it be able to get the column definitions from the parent Entity class?
I would also like to know if extending BaseObservable (which I need to get the Data Binding working) can cause problems with Room? BaseObservable has one private transient field, so maybe this is causing some issues with the code generation.
Are there any recommended patterns to deal with this, or will I just have to flatten my entity hierarchy?
After further investigation it turns out that Room Entities should not extend the BaseObservable class. It contains fields that can't be marked with #Ignore and break the code generation.
Room works well with inheritance. The annotations are processed as expected and the DB operations behave normally. You can extend from both an Entity and a POJO.
I have an entity that looks like this
#Entity(name = "encounter_pdf_export")
public class EncounterPDFExport<T extends Encounter> implements Serializable {
public static final long serialVersionUID = 1L;
#Id
#GeneratedValue
private Long pdfExportId;
#Any(metaColumn = #Column(name = "encounter_type"))
#Cascade(CascadeType.ALL)
#AnyMetaDef(
idType = "long",
metaType = "string",
metaValues = {
#MetaValue(value = "FooEncounter", targetEntity = FooEncounter.class)
})
#JoinColumn(name = "encounter_id")
private T encounter;
The abstract type that I'm extending is:
public abstract class Encounter {
public abstract Long getEncounterId();
}
Here is my Spring Data Repository
#Repository
public interface EncounterPDFExportRepository extends PagingAndSortingRepository<EncounterPDFExport, Long> {
EncounterPDFExport findOneByEncounter_encounterId(#Param("encounterId") Long encounterId);
}
I am getting a stack trace when starting up the application related to to the findOneByEncounter_encounterId method:
Caused by: java.lang.IllegalArgumentException: Unable to locate Attribute with the the given name [encounter] on this ManagedType [com.iimassociates.distiller.domain.EncounterPDFExport]
at org.hibernate.jpa.internal.metamodel.AbstractManagedType.checkNotNull(AbstractManagedType.java:144)
at org.hibernate.jpa.internal.metamodel.AbstractManagedType.getAttribute(AbstractManagedType.java:130)
at org.springframework.data.jpa.repository.query.QueryUtils.toExpressionRecursively(QueryUtils.java:468)
at org.springframework.data.jpa.repository.query.JpaQueryCreator$PredicateBuilder.getTypedPath(JpaQueryCreator.java:300)
at org.springframework.data.jpa.repository.query.JpaQueryCreator$PredicateBuilder.build(JpaQueryCreator.java:243)
at org.springframework.data.jpa.repository.query.JpaQueryCreator.toPredicate(JpaQueryCreator.java:148)
at org.springframework.data.jpa.repository.query.JpaQueryCreator.create(JpaQueryCreator.java:88)
at org.springframework.data.jpa.repository.query.JpaQueryCreator.create(JpaQueryCreator.java:46)
at org.springframework.data.repository.query.parser.AbstractQueryCreator.createCriteria(AbstractQueryCreator.java:109)
at org.springframework.data.repository.query.parser.AbstractQueryCreator.createQuery(AbstractQueryCreator.java:88)
at org.springframework.data.repository.query.parser.AbstractQueryCreator.createQuery(AbstractQueryCreator.java:73)
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery$QueryPreparer.<init>(PartTreeJpaQuery.java:116)
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery$CountQueryPreparer.<init>(PartTreeJpaQuery.java:237)
at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.<init>(PartTreeJpaQuery.java:65)
at org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy$CreateQueryLookupStrategy.resolveQuery(JpaQueryLookupStrategy.java:100)
I am assuming that either Spring Data JPA doesn't support abstracted/generic fields? If that's the case, would creating a #Query be a sufficient workaround?
Not sure if this will be helpful to anyone, but I did get this working.
Removed the abstract class and made it an interface with a single public getEncounterId() method
Modified FooEncounter to implement the above interface
Removed generics from the EncounterPDFExport class
Modified the encounter field to utilize the above interface rather than a generic
Apparently, I'm hitting some Hibernate bug/limitation when accessing fields within FooEncounter. Accessing Encounter within EncounterPDFExport works OK, though. I modified my Spring Data JPA Repository to look like the following (note the modification from finding by encounter.encounterId vs. just encounter):
#Repository
public interface EncounterPDFExportRepository extends PagingAndSortingRepository<EncounterPDFExport, Long> {
EncounterPDFExport findOneByEncounter(#Param("encounter") Encounter encounter);
}
The Hibernate bug in question seems to be related to https://jira.spring.io/browse/DATAJPA-836.
i'm using ViewScoped in my controller but i need to do something wired..
i want to mantain the data when using that view but if i leave that view, and then return i dont want the data there!
#Component("sponsorController")
#ViewScoped
public class SponsorController implements Serializable {
private static final long serialVersionUID = 1L;
#Autowired
private SponsorClientFacade ejbFacade;
should i switch scope?or this is the right one?
i can't do want i want with this way..
My solution was specify a onclick method in the hyperlynk and that method clear all views..
Thanks for the help
I am using spring mvc with hibernate and JPA. I have a Person class which is inherited by another class called Agent. The mapping is implemented as follows:
#Entity
#Table(name = "Person")
#Inheritance(strategy = InheritanceType.JOINED)
public class Person extends Auditable implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "PersonId")
protected Long id;
//other variables
...
}
#Entity
#PrimaryKeyJoinColumn(name = "PersonId")
public class Agent extends Person implements Serializable {
//additional agent specific variables go here
...
}
Saving new data is smooth and I have no problem there. however, when I edit data, everything except the id value is bound to the controller method's model attribute. I have verified that the id has been sent along with other items from the browser using chrome's developer tools. but the id field at the controller is always null and as a result the data is not updated. This is what my controller method looks like:
#RequestMapping(value = "register", method = RequestMethod.POST)
public #ResponseBody CustomAjaxResponse saveAgent(ModelMap model, #ModelAttribute("agent") #Valid Agent agent, BindingResult result) {
...
}
I suspect the problem is probably with my inheritance mapping because I have other classes inheriting from the Person class and I face a similar problem there as well.
Please help!
you need a public setter for id.
In cases like this I commonly use a specific dto for the form, and/or implement a conversion service that retrieves the entity via hibernate based on id and then performs a merge.