Select highest/lowest value for x in Data Object - jpa

my
#Entity
#Table(name = "Creditcard")
#AdditionalCriteria( ..... )
public class Customer implements Serializable {
#Id
#Column(name ="CustomerId")
private long customerId;
#Column(name = "cardNumber");
private String cardNumber;
#Column(name = "apply_date")
private java.sql.Date date;
}
Example Table Data for CustomerID 1234:
CustomerId|cardNumber|apply_date|....other fields
----------|----------|----------|----------------
0000000123|0000000001|2013-01-01|----------------
0000000123|0000000002|2013-09-10|----------------
Yes, I know, the Primary Key has to be a Composite Key (EmbeddedID), but I still have to figure it out.
Due to the #AdditionalCriteria I only get 1 entry (because the other card is "banned")
but I need to get the 'apply_date' from cardNumber '1'.
Is something like that possible?
Like:
#Column(name = "apply_date")
#GetMinValue(field_name = "CustomerId")
private java.sql.Date date;
Thanks in advance!

First, your entity should represent a row in the database, not all rows. So your entity probably should be a "CreditCard" entity, using "cardNumber" as the primary key, or what ever uniquely identifies the database row.
Then, since CustomerId seems to be a foreign key probably to a table that has customer data, you would have a Customer Entity that has a 1:M relationship to CreditCards. This customer entity could then have a transient date attribute that you set in a JPA postLoad event, getting the value from a JPQL query : "select cc.date from CreditCard cc where cc.customerId = :customerId";
Setting up an Customer entity that only uses a single card/row from a CreditCard table seems like a bad idea, as what will you do when the customer gets another creditCard assigned - it is the same customer, but a new card. If you use separate entity objects, you just keep the same Customer entity and assign a new creditcard object.

Related

JPA: receive several columns from table linked with current as manytoone

i'm new at JPA and need some advice.
I have two tables, Car and Driver linked as ManyTyOne. And I would obtain Car entity with info about several drivers. Now i can get from Driver only driver_id, it looks like this, but need to receive also drivers name and lastName.
Class Car:
#Entity
public class Car {
#JsonIgnoreProperties({"telephone", "mail",})
#ManyToOne
#JoinColumn(name = "driver_id"),
private Driver driver;
...
}
#Entity
class Driver:
#JsonIgnoreProperties({"telephone", "mail",})
public class Driver {
private Long id;
private String firstName;
private String lastName;
private String telephone;
private String mail;
...
}
Table car SQL:
CREATE TABLE `car` (
`id` decimal(20) unsigned NOT NULL AUTO_INCREMENT,
`driver_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (driver_id) REFERENCES driver(id),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
At first I think that it's possible to receive also drivers name and surname the next way:
#JoinColumns({#JoinColumn(name = "driver_id"),
#JoinColumn(name = "first_name"),
#JoinColumn(name = "last_name")})
But documentation says, that #JoinColums is sutable only for composite fk.
Please give me a hint, how can i do whats needed.
Assuming your Driver class is an entity (you didn't put in the #Entity annotation in the above code.)
Your current mapping is saying that each driver can drive multiple cars. Since the many to one only exists on the Car side, there's no way to go from Driver to Car. To do that, you would need to have a #OneToMany mapping going from Driver to Car. (Also, shouldn't this be a many to many mapping? each Driver can drive multiple cars. and each car can have multiple drivers?)
In any case, given the mapping as above, you should be able to access driver.firstName and driver.lastName. What is the error when you are attempting to do that?

spring data JPA association in Map

I'm trying to use Map in Spring Data JPA to handle the relationship to store records of equipment quantity.
I followed this guide to create the entity.
Meeting{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "meeting_id", updatable = false)
#JsonIgnore
private int id;
#ElementCollection
#MapKeyColumn(name = "equipment_type")
#MapKeyEnumerated(EnumType.STRING)
private Map<EquipmentType, Integer> equipment = new HashMap<>();
}
EquipmentType is an Enum.
This is the table for the property:
CREATE TABLE IF NOT EXISTS meeting_equipment (
meeting_id INTEGER NOT NULL REFERENCES meeting (meeting_id),
equipment_type VARCHAR(10) NOT NULL,
quantity INTEGER NOT NULL DEFAULT 0
);
Once I try to create a meeting entity, I get error ERROR:column "meeting_meeting_id" of relation "meeting_equipment" does not exist
May I know what's the problem here?
Your table meeting_equipment does not match what JPA is expecting.
It has a column meeting_id but your JPA implementation expects meeting_meeting_id
Either rename the column to the expected meeting_meeting_id or configure your mapping to use the current column name. I think this might do the trick:
#JoinTable(joinColumns={#JoinColumn(name="meeting_id")}
Of course, you probably can create your own naming strategy if you have many cases like this and want to keep your column names as they are.

JaVers, SpringDatat, JPA: Querying for Entity Update inside a Collection

I'm new to Stackoverflow, so I will make my best to conforms with usage. I was wondering if there were a way to get a complete list of changes/snapshots of a given Entity. For now it works well with edition of Singular Properties, as well as Addition and Deletion to Collection Property. But I'm unable to find when a Child Entity in the Collection Property was updated.
Given two Entities, and a LinkEntity:
#Entity
class Person {
#Id
Long id;
#OneToMany(mappedBy = "person", cascade = CascadeType.ALL)
Set<LinkAddress> addresses;
}
#Entity
class Address {
#Id
Long id;
#OneToMany(mappedBy = "address")
Set<Address> persons;
}
#Entity
class LinkPersonAddress {
#Id
Long id;
#ManyToOne
#ShallowReference
Person person;
#ManyToOne
#ShallowReference
Address address;
String linkType;
}
My use case is following. I get a specific Person by Id #1, and then mutate the type of specific Address (ie. HOME --> WORK). I save the Person back with the modified Set and let JPA Cascade my changes. Although all Spring Data Repositories for Person, Address, and LinkPersonAddress are annotated with #JaversSpringDataAuditable, I cannot retrieve this "update" using Javers QueryBuilder with the class Person and Id #1. It makes sense as I should query the class LinkPersonAddress instead, but how can I specify that I want only the changes from LinkPersonAddress relevant to Person with Id #1.
PS: Please apologize any typos in code snippets, as I didn't write it in my Dev Environment.
Let's start from the mapping. You did it wrong, Address is a classical ValueObject (see https://javers.org/documentation/domain-configuration/#value-object) not Entity. Because:
Address doesn't have its own identity (primary key genereted by a db sequence doesn't count)
Address is owned by the Person Entity. Person with its Addresses forms the Aggregate.
When you correct the mapping, you can use ChildValueObjects filter, see https://javers.org/documentation/jql-examples/#child-value-objects-filter

Storing ManyToMany with extra column using merge method

I have an entity class that is simply a ManyToMany with extra column, as follows:
#Entity
#Table(name = "view_templates_device_types")
public class ViewTemplateDeviceTypeEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#ManyToOne
#JoinColumn(name = "view_template_id")
private ViewTemplateEntity viewTemplate;
#Id
#ManyToOne
#JoinColumn(name = "device_type_id")
private DeviceTypeEntity deviceType;
#Column(name = "priority", nullable = false)
private int priority;
public ViewTemplateDeviceTypeEntity() {
}
...
}
I noticed that when I create a new object of this type, set viewTemplate and deviceType to values that have corresponding data in the db and I call entityManager.persist(entity) the data is stored. But when I call entityManager.merge(entity) instead of persist I get an exception:
SQL Error: 1048, SQLState: 23000
Column 'view_template_id' cannot be null
I thought that calling merge should result with data inserted into database in case it is not stored yet. It is quite important to me to use merge here (because of cascades). What can I do to make it work?
As per the JPA spec, section 2.4
"A composite primary key must correspond to either a single persistent field or property or to a set of such fields or properties as described below. A primary key class must be defined to represent a composite primary key. Composite primary keys typically arise when mapping from legacy databases when the database key is comprised of several columns. The EmbeddedId or IdClass annotation is used to denote a composite primary key. See Sections 11.1.17 and 11.1.22.".
So you either need #IdClass or #EmbeddedId. Anything else is non-portable and prone to error. I am very surprised of any JPA provider that does not throw out warnings for this.

How exactly work the #OneToMany JPA annotation in this example? Is it related to a table column or an entity class field?

I have 2 DB tables named respectivelly T_ACCOUNT and T_ACCOUNT_BENEFICIARY.
These tables have the following structure:
create table T_ACCOUNT (ID integer identity primary key, NUMBER varchar(9), NAME varchar(50) not null, CREDIT_CARD varchar(16), unique(NUMBER));
create table T_ACCOUNT_BENEFICIARY (ID integer identity primary key, ACCOUNT_ID integer, NAME varchar(50), ALLOCATION_PERCENTAGE decimal(5,2) not null, SAVINGS decimal(8,2) not null, unique(ACCOUNT_ID, NAME));
And the T_ACCOUNT table is bound to the T_ACCOUNT_BENEFICIARY table with a one to many relationship, this is the graphical representation:
So this is the first class named Account that map the T_ACCOUNT table:
#Entity
#Table(name="T_ACCOUNT")
public class Account {
#Id
#GeneratedValue
#Column(name="id")
private Long entityId;
#Column(name="NUMBER")
private String number;
#Column(name="NAME")
private String name;
#OneToMany
#JoinColumn(name="ACCOUNT_ID")
private Set<Beneficiary> beneficiaries = new HashSet<Beneficiary>();
#Column(name="CREDIT_CARD")
private String creditCardNumber;
// GETTERS & SETTERS
}
And this is the Beneficiary class that map the T_ACCOUNT_BENEFICIARY table:
/**
* A single beneficiary allocated to an account. Each beneficiary has a name (e.g. Annabelle) and a savings balance
* tracking how much money has been saved for he or she to date (e.g. $1000).
*/
#Entity
#Table(name="T_ACCOUNT_BENEFICIARY")
public class Beneficiary {
#Id
#GeneratedValue
#Column(name="ID")
private Long entityId;
#Column(name="NAME")
private String name;
#Embedded
#AttributeOverride(name="value",column=#Column(name="ALLOCATION_PERCENTAGE"))
private Percentage allocationPercentage;
#Embedded
#AttributeOverride(name="value",column=#Column(name="SAVINGS"))
private MonetaryAmount savings = MonetaryAmount.zero();
As you can see into the Account I have the beneficiaries field that implement the one to may relationship
#OneToMany
#JoinColumn(name="ACCOUNT_ID")
private Set<Beneficiary> beneficiaries = new HashSet<Beneficiary>();
I know that, on the DB, this relationship is implemented by the ACCOUNT_ID field of the T_ACCOUNT_BENEFICIARY table (so multiple row of the T_ACCOUNT_BENEFICIARY table can have the same value of the ACCOUNT_ID field and this means that a single row of the T_ACCOUNT table can be associated to more than one rows of T_ACCOUNT_BENEFICIARY table).
As you can see in the previous sippet there is the #JoinColumn(name="ACCOUNT_ID") annotation.
My doubt is generated by the fact that I have an ACCOUNT_ID column on my T_ACCOUNT_BENEFICIARY table, infact:
create table T_ACCOUNT_BENEFICIARY (ID integer identity primary key, ACCOUNT_ID integer, NAME varchar(50), ALLOCATION_PERCENTAGE decimal(5,2) not null, SAVINGS decimal(8,2) not null, unique(ACCOUNT_ID, NAME));
but this column seems to not be mapped on the Beneficiary that map this T_ACCOUNT_BENEFICIARY table.
So my doubts is: the #JoinColumn(name="ACCOUNT_ID") is working at relational level performing the join operation on the ACCOUNT_ID column of the table mapped by the Beneficiary entity (T_ACCOUNT_BENEFICIARY) or am I missing something? How exactly is performed this join?
If my interpretation is right can I work at entity level and say to join the beneficiaries field of my Account entity class to a new accountId field inserted into my Beneficiary entity class and mapping the ACCOUNT_ID column of the T_ACCOUNT_BENEFICIARY table?
Tnx
It seems is a Unidirectional OneToMany relationship
In JPA 2.0 a #JoinColumn can be used on a OneToMany to define the foreign key
I'm not sure if I understand your question. But what you have done with your #JoinColumn annotation is correct and Hibernate will execute appropriate SQL statements when you have multiple beneficiaries for your account. For example executing multiple INSERTS if you have two Beneficiaries for an Account. And yes using the #JoinColumn annotation is at the hibernate level. If you want to access an Account from a Beneficiary entity you would need to define a Bidirectional relationship in the Beneficiary class like below.
#Entity
#Table("T_ACCOUNT_BENEFICIARY")
public class Beneficiary {
#ManyToOne(mappedBy = "beneficiaries")
Account account;
...
}