I need advice regarding a many-to-many relationship between KeyStoreEntity
and it's 3 child entities ( KeyPairEntity, SecretKeyEntity, CertificateEntity
). I will use CertificateEntity
for this example as other 2 follow the same pattern/issue. My extended class BaseRdbmsEntity
is a @MappedSuperclass
with id, name and description attributes.
I had no problems with @ManyToMany
on both sides and using Map<String, CertificateEntity>
on KeystoreEntity
side to get certificates by their alias along with Map<String, KeyStoreEntity>
on CertificateEntity
to get the aliases and associated keystores.
Then I realized I'd blown it as a certificate could easily have the SAME alias in different keystores...thus CertificateEntity
map keys can clash and one value will wipe out subsequent value stored therein during a repository query.
I need to reverse the key/value types for the map attribute in CertificateEntity
to Map<KeyStoreEntity, String>
. It's unclear to me how I do a @MapKeyValue
(I realize this doesn't exist) to get alias as value in map...and not as key.
I've attempted to fix the problem by using @JoinTable
annotations but am not seeing an equivalent of @MapKeyColumn
for value-side of map. What I want is KeyStoreEntity
as key and String alias
as the value.
@Entity(name = "keystores")
@Table(name = "pki_keystores")
public class KeyStoreEntity extends BaseRdbmsSecurityEntity
{
@MapKeyColumn(name="alias")
@ManyToMany
(
fetch = FetchType.LAZY,
cascade = {CascadeType.PERSIST, CascadeType.MERGE}
)
private Map<String, CertificateEntity> certificates;
...snip...
}
@Entity(name = "certificates")
@Table(name = "pki_certificates", uniqueConstraints = {
@UniqueConstraint(columnNames = {"issuerDn", "serialNumber"})
})
public class CertificateEntity extends BaseRdbmsSecurityEntity
{
@MapKeyColumn(name="alias")
@ManyToMany(
fetch = FetchType.LAZY,
cascade = {CascadeType.PERSIST, CascadeType.MERGE},
mappedBy = "certificates",
targetEntity = KeyStoreEntity.class
)
private Map<String, KeyStoreEntity> keystores;
// Map type for above needs to be <KeyStoreEntity, String>
...snip...
}
I'm expecting a lazy fetch to work with k/v reversed on the CertificateEntity.keystores
side of the relationship. My expectation is I only need to tweak/add an annotation to CertificateEntity
for keystores
attribute.
Here's an example of uni/bidirectional relationship Many-to-Many. I hope you would easily adapt it to your code) It's just trivial example with List
. Check out this question on SO, too
unidirectional
: @Entity
public class User {
@Id
@GeneratedValue
@Column(name = "user_id")
private long id;
...
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
private List<Role> roles = new ArrayList<>();
public void addRoles(Role role) {
roles.add(role);
}
public void removeRoles(Role role) {
roles.remove(role);
}
}
@Entity
public class Role {
@Id
@GeneratedValue
@Column(name = "role_id")
private int id;
@Column(name = "role")
private String role;
}
bidirectional
: @Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@ToString(exclude = "stockmarkets")
@Table(name = "trader")
public class Trader {
@Id
@GeneratedValue
@Column(name = "trader_id")
private Long id;
@Column(name = "trader_name")
private String traderName;
@ManyToMany(fetch = FetchType.LAZY,
cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
})
@JoinTable(name = "TRADER_STOCKMARKET",
joinColumns = { @JoinColumn(name = "trader_id") },
inverseJoinColumns = { @JoinColumn(name = "stockmarket_id") })
private List<Stockmarket> stockmarkets = new ArrayList<>();
/*
We need to add methods below to make everything work correctly
*/
public void addStockmarket(Stockmarket stockmarket) {
stockmarkets.add(stockmarket);
stockmarket.getTraders().add(this);
}
public void removeStockmarket(Stockmarket stockmarket) {
stockmarkets.remove(stockmarket);
stockmarket.getTraders().remove(this);
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@ToString(exclude = "traders")
@Table(name = "stockmarket")
public class Stockmarket{
@Id
@GeneratedValue
@Column(name = "stockmarket_id")
private Long id;
@Column(name = "stockmarket_name")
private String stockmarketName;
@ManyToMany(mappedBy="stockmarkets")
private List<Trader> traders = new ArrayList<>();
/*
We need to add methods below to make everything work correctly
*/
public void addTrader(Trader trader) {
traders.add(trader);
trader.getStockmarkets().add(this);
}
public void removeTrader(Trader trader) {
traders.remove(trader);
trader.getStockmarkets().remove(this);
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.