I'm struggling to make a query that inner join 3 tables and have a where clause. It's like my where doesn't exist.
Here are my entities:
CarModel entity:
#Entity
#Table(name = "CARMODEL")
public class CarModel implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#OneToMany(mappedBy = "carModel")
private List<MyCars> myCars;
MyCars entity
#Entity
#Table(name = "MYCARS")
public class MyCars implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#ManyToOne
#JoinColumn(name = "CarModel_id")
private CarModel carModel= new CarModel();
#ManyToOne
#JoinColumn(name = "user_id")
private User user = new User();
User entity:
#Entity
#Table(name = "USER")
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#OneToMany(mappedBy = "user")
private List<MyCars> myCars;
Here is the graphical representation of these three entities:
And here is one of the queries i have tried:
public List<CarModel> findMyCarsByUserId(long IdUser)
{
String requete = "SELECT DISTINCT cm\n" +
"FROM MyCars ms\n" +
" INNER JOIN CarModel cm INNER JOIN User u where u.id=2";
Query query = em.createQuery(requete);
//query.setParameter("iduser", IdUser);
List<CarModel> cars = null;
cars = (List<CarModel>) query.getResultList();
return cars;
}
So here I'm trying to get all the ModeleVehicule for a given user_id. But I keep having all the ModeleVehicule of the table, despite the where clause.
I have a mysql query working for what I want:
SELECT cm.marque,cm.modele, cm.motorisation, cm.anneeModele, cm.puissance
FROM carmodel cm
INNER JOIN mycars ms ON cm.ID = ms.ModeleVehicule_id
INNER JOIN user u ON ms.user_id = u.ID
WHERE ms.user_id = 1
What am I doing wrong ?
Related
I have an issue trying to generate multiple relationship in JPA with three Entities.
Order
Product
Modifier
I have an Entity to handle the relationship many to many.
OrderProducts (order_id and product_id)
Contains the relationship of one order can have multiple products
OrderDetails (order_products_id and modifier_id)
Contains the id of the previous relationship Order-Products and the Id of the modifier which is a set of multiple values that can affect the price of the product.
Not quite sure how to handle this kind of relationship in JPA as I'm new to it.
You need a join entity with a composite key. You will need to research it further.
Your entities:
#Entity
#Table(name = "ordertable")
#Data
public class Order {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#OneToMany(mappedBy = "order")
#EqualsAndHashCode.Exclude
private Set<OrderProductModifier> products;
}
#Entity
#Table(name = "product")
#Data
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#EqualsAndHashCode.Exclude
private BigDecimal unitPrice;
}
#Entity
#Table(name = "modifier")
#Data
public class Modifier {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#EqualsAndHashCode.Exclude
private BigDecimal modifier;
}
And the entity that ties it all together will need to have the foreign keys for each of the above entities, as you have noted.
#Entity
#Table(name = "orderproductmodifier")
#Data
public class OrderProductModifier {
#EmbeddedId
private OrderProductModifierId id;
#MapsId("orderId")
#ManyToOne
#EqualsAndHashCode.Exclude
#ToString.Exclude
private Order order;
#MapsId("productId")
#ManyToOne
#EqualsAndHashCode.Exclude
private Product product;
#MapsId("modifierId")
#ManyToOne
#EqualsAndHashCode.Exclude
private Modifier modifier;
}
#SuppressWarnings("serial")
#Embeddable
#Data
public class OrderProductModifierId implements Serializable {
private Long orderId;
private Long productId;
private Long modifierId;
}
This is pretty simple to use:
private void run() {
EntityManagerFactory factory = Persistence.createEntityManagerFactory("UsersDB");
EntityManager em = factory.createEntityManager();
em.getTransaction().begin();
Product product = new Product();
product.setUnitPrice(BigDecimal.TEN);
em.persist(product);
Modifier modifier = new Modifier();
modifier.setModifier(new BigDecimal(".90"));
em.persist(modifier);
Order order = new Order();
em.persist(order);
OrderProductModifier opm = new OrderProductModifier();
opm.setId(new OrderProductModifierId());
opm.setOrder(order);
opm.setProduct(product);
opm.setModifier(modifier);
em.persist(opm);
em.getTransaction().commit();
em.clear();
Order o = em.createQuery("select o from Order o join fetch o.products where o.id = 1", Order.class).getSingleResult();
System.out.println("Order for " + o.getProducts());
System.out.println("Order cost " + o.getProducts().stream().map(p->p.getProduct().getUnitPrice().multiply(p.getModifier().getModifier()).doubleValue()).collect(Collectors.summingDouble(Double::doubleValue)));
}
The above query could be better, but that will give you something to work on.
I have an Entity_A that has OneToMany relationship with Entity_B.
Entity_B has a flag which indicates whether it is active.
How can I select join entity A and only entity B if it is active?
JPA Query:Documention
SELECT DISTINCT entA FROM Entity_A entA JOIN FETCH entA.entityBSet as entB WHERE entB.active = true
Update
- try #where
#Entity
public class Entity_A {
#Id
#Column(name = "ID")
private Integer id;
#OneToMany(mappedBy = "entityA")
#Where("active = true")
private Set<Entity_B> entityBSet;
}
#Entity
public class Entity_B {
#Id
#Column(name = "ID")
private Integer id;
#Id
#Column(name = "ACTIVE")
private Integer active;
#ManyToOne
private Entity_A entityA;
}
I have three tables each mapping to one of these entities. The 'assigned' table acts as the relationship between 'users' and 'roles' with a foreign key to each table. How would I map this on my entities so that I can get a Set of EntityRoles from the UserEntity? I can't quite figure out how to make this work. Is this even possible?
#Entity
#Table(name = "users")
public class UserEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="user_id")
private long id;
#Column(name="user_username")
private String username;
#Column(name="user_password")
private String password;
#Column(name="user_email")
private String email;
//I want to be able to get a set of RoleEntities
#OneToMany(fetch = FetchType.LAZY, mappedBy = "id")
private Set<RoleEntity> roles;
}
#Entity
#Table(name = "assigned")
public class AssignedEntity implements Serializable {
#Id
//#Column(name = "assigned_role")
#ManyToOne(targetEntity = RoleEntity.class, fetch = FetchType.LAZY)
#JoinColumn(name = "fk_role")
private long roleId;
#Id
//#Column(name = "assigned_user")
#ManyToOne(targetEntity = UserEntity.class, fetch = FetchType.LAZY)
#JoinColumn(name = "fk_user")
private long userId;
}
#Entity
#Table(name = "roles")
public class RoleEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="role_id")
#OneToOne(fetch = FetchType.LAZY, mappedBy="roleId")
private long id;
#Column(name="role_name")
private String name;
}
You are using an incorrect/inconvenient mapping. Always keep things as simply as possible.
#Entity
#Table(name = "users")
public class User {
#Id
#GeneratedValue
private Long id;
#ManyToMany(fetch = FetchType.LAZY)
private List<Role> roles;
}
#Entity
#Table(name = "roles")
public class Role {
#Id
private Long id;
#Column
private String name;
}
A persistent provider will create a (valid) join table for you. You can specify the name of the join table using #JoinTable annotation. Also you will need to think about auto generation values of id for the Role entity: the roles table is something like a reference data table. So, probably, you will need to hardcode the id values.
To get user roles (in the persistent context):
user.getRoles()
This is a RBAC module,There is three basic table user,role and permission and middle mapping table user_role and role_permission.
#Entity
#Table(name = "USER")
public class User implements Serializable {
#Id
private String userId;
...
}
#Entity
#Table(name = "ROLE")
public class Role implements Serializable {
#Id
private String roleId;
...
}
#Entity
#Table(name = "PERMISSION")
public class Permission implements Serializable {
#Id
private String permissionId;
...
}
#Entity
#Table(name = "USER_ROLE")
public class UserRole implements Serializable {
#Id
#GenericGenerator(name = "uuidGenerator", strategy = "uuid")
#GeneratedValue(generator = "uuidGenerator")
#Column(name = "ID")
private String id;
#ManyToOne
#JoinColumn(name = "USERID")
private User user;
#ManyToOne
#JoinColumn(name = "ROLEID")
private Role role;
...
}
#Entity
#Table(name = "ROLE_PERMISSION")
public class RolePermission implements Serializable {
#Id
private String id;
#ManyToOne
#JoinColumn(name = "PERMISSIONID")
private Permission permission;
#ManyToOne
#JoinColumn(name = "ROLEID")
private Role role;
...
}
and now i want to find all permission by user.id, SQL express like this:
select rp.* from Role_Permission rp,User_Role ur where ur.roleId = rp.roleId and ur.userId = :id
but by Criteria API:
public Predicate toPredicate(Root<RolePermission> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
List<Predicate> predicates = new ArrayList<Predicate>();
if (StringUtil.isNotEmpty(userId)) {
final Root<UserRole> userRoleRoot = criteriaQuery.from(UserRole.class);
Join<RolePermission,UserRole> join = root.join("role", JoinType.INNER);
Predicate predicate = criteriaBuilder.equal(join.get("roleId"), root.get("role").get("roleId"));
predicate = criteriaBuilder.and(predicate,criteriaBuilder.equal(userRoleRoot.<UserRole>get("user").get("id"), userId));
predicates.add(predicate);
}
return criteriaBuilder.and(predicates.toArray(new Predicate[]{}));
}
and query build result is:
select count(rolepermis0_.id) as col_0_0_ from role_permission rolepermis0_ inner join role role2_ on rolepermis0_.roleid=role2_.roleid cross join user_role userrole1_ where role2_.roleid=rolepermis0_.roleid and userrole1_.userid=?
but why here role_permission cross join user_role, how role_permission join user_role by criteria API ?
thanks a lot.
final Subquery<UserRole> userRoleSubquery = criteriaQuery.subquery(UserRole.class);
final Root<UserRole> userRole = userRoleSubquery.from(UserRole.class);
userRoleSubquery.select(userRole.<UserRole>get("id"));
userRoleSubquery.where(criteriaBuilder.equal(root.get("role").get("roleId"), userRole.get("role").get("roleId")), criteriaBuilder.equal(userRole.get("user").get("id"), userId));
Predicate predicate = criteriaBuilder.exists(userRoleSubquery);
predicates.add(predicate);
I want to build the following pseudo query
Select a From APDU a where a.group.id= :id
group is a field in APDU class of the type APDUGroup.class.
I just want to get a list of APDUs based on APDUGroup's id.
How do i do that using a standard JPA query?
UPDATE
Yes, I have tried the above query and tried other variations for hours before posting in S/O. Here is the generated SQL for the query above:
SELECT t1.ID, t1.status, t1.type, t1.modified, t1.response, t1.expectedSize, t1.created, t1.description, t1.sequence, t1.name, t1.command, t1.recurring, t1.auth, t1.createdBy, t1.APDUGroup, t1.modifiedBy FROM APDUGroup t0, APDU t1 WHERE ((t0.ID = ?) AND (t0.ID = t1.APDUGroup))
The query looks okay but nothing get selected from my table.
There are at least 100 APDUs with APDUGroup = 1 in my test database.
I'm using eclipselink as the JPA provider.
Given the following Entities:
#Entity
public class APDU implements Serializable {
#Id
#GeneratedValue
private Long id;
#ManyToOne
private APDUGroup group;
//...
}
#Entity
public class APDUGroup implements Serializable {
#Id
#GeneratedValue
private Long id;
//...
}
The following query will return a list of APDUs for a given APDUGroup id:
select a from APDU a where a.group.id = :id
Oh, wait, that's your query :)
Entity 1:
#Entity
#Getter
#Setter
#Table(name = "invoices")
public class Invoice implements Serializable {
#Id
#GeneratedValue
#Column(name = "invoice_id", updatable = false, nullable = false)
private Long invoiceId;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "person_id", referencedColumnName = "person_id", insertable = false, updatable = false, nullable = false)
private Person person;
//...
}
Entity 2:
#Entity
#Getter
#Setter
#Table(name = "people")
public class Person implements Serializable {
#Id
#GeneratedValue
#Column(name = "person_id", updatable = false, nullable = false)
private Long personId;
//...
}
Finally, Your Data Access Object (JPA Repository)
#Repository
public interface InvoiceRepository extends JpaRepository<Invoice, Long> {
#Query(value="SELECT x FROM Invoice x WHERE x.person.personId = :myPersonId")
List<Invoice> findInvoiceByPersonId (long myPersonId);
}
I hope this example has been helpful :)