I have this code (just multiply the number of attributes by ALOT):
#Entity
#Table(name = "MY_TABLE")
#Immutable
public class MyEntity {
#Id
#Column(name = "ID")
private String id;
public static final String PROPERTYNAME_ID = "id";
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
/* used by JPA, needs to have same getters/setters as MyEntity */
public class MyEntityCriteria {
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
Is there a way to share the attributes, getters and setters between those class?? ('extends' doesn't work as it also shares annotations...)
Related
I'm experimenting with mapstruct and follow this tutorial:
mapstruct tut
I have this entity:
#Entity
public class Company {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq_company")
#SequenceGenerator(name = "seq_company", allocationSize = 1)
#Column(nullable = false, updatable = false)
private Long id;
private String name;
private String shortName;
public Company() {
}
public Company(Long id, String name, String shortName) {
this.id = id;
this.name = name;
this.shortName = shortName;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getShortName() {
return shortName;
}
public void setShortName(String shortName) {
this.shortName = shortName;
}
}
And this is the simple dto:
public class CompanyDto {
#JsonProperty("id")
private Long id;
#JsonProperty("name")
private String name;
#JsonProperty("shortName")
private String shortName;
}
And here is the mapper interface:
#Mapper(componentModel = "spring")
public interface CompanyMapper {
CompanyDto companyToCompanyDto(Company company);
Company companyDtoToCompany(CompanyDto companyDto);
List<CompanyDto> companiesToCompanyDtos(List<Company> companies);
}
I certanly oversee something, because there is no setters in the generated implementation, f. e.:
#Override
public Company companyDtoToCompany(CompanyDto companyDto) {
if ( companyDto == null ) {
return null;
}
Company company = new Company();
return company;
}
What goes here wrong?
I've noticed that your CompanyDto class has private fields but no getters or setters. There is no standard way to access the fields in that class. You might need to add those in order to map in or out of that class.
I use EclipseLink and I get very strange results. Please, consider the following code:
This code works:
#Entity
#Table(name = "someTable")
public class SomeClass{
#Id// PAY ATTENTION TO THIS LINE
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#Column (name = "somecol")// PAY ATTENTION TO THIS LINE
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
This code also works:
#Entity
#Table(name = "someTable")
public class SomeClass{
#Id// PAY ATTENTION TO THIS LINE
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
//#Column (name = "somecol")// PAY ATTENTION TO THIS LINE
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
This code also works:
#Entity
#Table(name = "someTable")
public class SomeClass{
private String id;
#Id// PAY ATTENTION TO THIS LINE
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
//#Column (name = "somecol")// PAY ATTENTION TO THIS LINE
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
This code DOESN'T work:
#Entity
#Table(name = "someTable")
public class SomeClass{
private String id;
#Id // PAY ATTENTION TO THIS LINE
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#Column (name = "somecol")// PAY ATTENTION TO THIS LINE
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
I get the following exception:
Exception Description: Entity class [class SomeClass] has no primary key specified. It should define either an #Id, #EmbeddedId or an #IdClass. If you have defined PK using any of these annotations then make sure that you do not have mixed access-type (both fields and properties annotated) in your entity class hierarchy.
at org.eclipse.persistence.exceptions.ValidationException.noPrimaryKeyAnnotationsFound(ValidationException.java:1425)
at org.eclipse.persistence.internal.jpa.metadata.accessors.classes.EntityAccessor.validatePrimaryKey(EntityAccessor.java:1542)
at org.eclipse.persistence.internal.jpa.metadata.accessors.classes.EntityAccessor.processMappingAccessors(EntityAccessor.java:1249)
at org.eclipse.persistence.internal.jpa.metadata.accessors.classes.EntityAccessor.process(EntityAccessor.java:699)
at org.eclipse.persistence.internal.jpa.metadata.MetadataProject.processStage2(MetadataProject.java:1808)
at org.eclipse.persistence.internal.jpa.metadata.MetadataProcessor.processORMMetadata(MetadataProcessor.java:573)
at org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessor.processORMetadata(PersistenceUnitProcessor.java:607)
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.predeploy(EntityManagerSetupImpl.java:1948)
at org.eclipse.persistence.internal.jpa.deployment.JPAInitializer.callPredeploy(JPAInitializer.java:100)
at org.eclipse.persistence.jpa.PersistenceProvider.createEntityManagerFactoryImpl(PersistenceProvider.java:104)
at org.eclipse.persistence.jpa.PersistenceProvider.createEntityManagerFactory(PersistenceProvider.java:188)
at org.eclipse.gemini.jpa.ProviderWrapper.createEntityManagerFactory(ProviderWrapper.java:128)
at org.eclipse.gemini.jpa.proxy.EMFServiceProxyHandler.createEMF(EMFServiceProxyHandler.java:151)
at org.eclipse.gemini.jpa.proxy.EMFServiceProxyHandler.syncGetEMFAndSetIfAbsent(EMFServiceProxyHandler.java:127)
at org.eclipse.gemini.jpa.proxy.EMFServiceProxyHandler.invoke(EMFServiceProxyHandler.java:73)
at com.sun.proxy.$Proxy8.createEntityManager(Unknown Source)
Why doesn't last code work? How to explain it?
That's because there is something like #Access which you must specify on a entity and field level if you would like to use the mixed mode. There are two values AccessType.PROPERTY and AccesType.FIELD.
The default access type is defined by where you put your identifier annotation (#Id). If you put it on the field - it will be AccessType.FIELD, if you put it on the getter - it will be AccessType.PROPERTY. - edited, not defined by JPA.
If you want to annotate not fields but properties (still having #Id on field) you must define a getter and annotate it as AccessType.PROPERTY. (or vice versa for #Id on getter).
I'm trying to filter a result set by a foreign key:
createCriteria(Person.class).add(Restrictions.ne("position", 1L)).list()
But getting this exception: org.hibernate.PropertyAccessException: could not get a field value by reflection getter of com.example.model.Position.id
Here are the necessary JPA entities (trimmed down to the necessary fields):
#Entity
#Table
public class Person {
#Id
#GeneratedValue
private Long id;
#ManyToOne
#JoinColumn(nullable = false)
#ForeignKey(name = "person_position_fkey")
private Position position;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Position getPosition() {
return position;
}
public void setPosition(Position position) {
this.position = position;
}
}
#Entity
#Table
public class Position {
#Id
#GeneratedValue
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
Try Restrictions.ne("position.id", 1L)
I have a Hibernate mapping that looks something like this:
class A {
private Long id;
private Map<C,String> someMap;
...
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#ElementCollection(targetClass=String.class, fetch=FetchType.EAGER)
public Map<C, String> getSomeMap() {
return someMap;
}
pubic void setSomeMap(Map<C,String> someMap){
this.someMap = someMap;
}
}
class B {
private Long id;
private A a;
...
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#OneToOne
public A getA(){
return a;
}
public void setA(A a){
this.a = a;
}
}
class C {
private Long id;
...
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
How can I do a query (with criteria) to get all "В" which have such "A" which have, for example, "test" as value in "someMap"? Or can I do it only with clear sql?
Interesting. I've never done a map where key is the object, and string the value. Generally it's the other way around. Can you keep the string on C, and use a straight collection? Or is there a funky many to many relationship going on here?
If I create a Customer and Controller, then associate my Controller with a customer it saves fine.
If I then remove my controller it doesn't remove the relationship between them.
This causes an EntityNotFoundException when I load the Customer.
javax.persistence.EntityNotFoundException: Unable to find Controller with id 22
I'd like to know how to map this so that when a Controller is deleted the relationship is also deleted.
Database Tables
customer
controller
customer_controllers - mapping table.
The Controller's id is not getting removed from the customer_controllers mapping table.
#Entity
public class Customer implements Serializable{
private Integer id;
private Set<Controller> controllers;
#Id
#GeneratedValue
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#ManyToMany(cascade={CascadeType.ALL})
public Set<Controller> getControllers()
{
return controllers;
}
public void setControllers(Set<Controller> controllers)
{
this.controllers = controllers;
}
}
#Entity
public class Controller implements Serializable{
private Integer id;
private String name;
private String abbreviation;
#Id
#GeneratedValue
public Integer getId()
{
return id;
}
public void setId(Integer id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getAbbreviation()
{
return abbreviation;
}
public void setAbbreviation(String abbreviation)
{
this.abbreviation = abbreviation;
}
}
If you have a ManyToMany then you should map Controller to Customer with a
#ManyToMany(mappedBy="controllers")
or the other way around, depending on which side is the owning side.
As you have it now the relation is not fully defined and it will fail on events like "Cascade".
Have you checked the javadoc for #ManyToMany?
It includes the above example mappings.
you need to make the relationship bidirectional, so that the controller object is aware of its relationship to the customer. Yhis means that when the controller is deleted the record in the join table is also deleted.
This isn't the exact mapping but it gives you the idea.
#Entity
public class Controller implements Serializable{
private Integer id;
private String name;
private String abbreviation;
private Set<Customer> customers;
#Id
#GeneratedValue
public Integer getId()
{
return id;
}
public void setId(Integer id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getAbbreviation()
{
return abbreviation;
}
public void setAbbreviation(String abbreviation)
{
this.abbreviation = abbreviation;
}
#ManyToMany(cascade={CascadeType.ALL})
public Set<Customer> getCustomers()
{
return customers;
}
public void setCustomers(Set<Customers> customers)
{
this.customers= customers;
}
}