I was trying to query a embedded collection inside an entity using a query similar to the following:
Query q = em.createQuery("SELECT u FROM User u , in (u.addresses) a
WHERE a.state='xx'");
The query didn't return any result nor did it throw any error. I am using Datanucleus and MongoDb. Does Datanucleus have any limitation on such queries?
And the entity looked like:
public class User{
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
protected long id;
#ElementCollection
protected List<Address> addresses;
public User(){
}
...
#Embeddable
public class Address {
private String street;
private String city;
private String state;
private Integer zip;
public Address(){
}
...
Related
This question is already phrased as an issue here: https://github.com/spring-projects/spring-data-jpa/issues/2369 but for lack of a reaction there I am copying the contents of that issue here, hoping that somebody might find what's wrong with my code or confirm that this could be a bug:
I've set up an example project here that showcases what seems to be a bug in Spring Data projections: https://github.com/joheb-mohemian/gs-accessing-data-jpa/tree/primary-key-join-column-projection-bug/complete
I have a Customer entity that has a OneToOne mapping to an Address entity:
#Entity
public class Customer {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String firstName;
private String lastName;
#OneToOne(mappedBy = "customer", cascade = CascadeType.ALL)
#PrimaryKeyJoinColumn
private Address address;
//...
}
#Entity
public class Address {
#Id
#Column(name = "customer_id")
private Long id;
#OneToOne
#MapsId
#JoinColumn(name = "customer_id")
private Customer customer;
private String street;
//...
}
Then there are simple projection interfaces:
public interface CustomerProjection {
String getFirstName();
String getLastName();
AddressProjection getAddress();
}
public interface AddressProjection {
String getStreet();
}
But when I try to fetch a projected entity from a repository method like this one:
public interface CustomerRepository extends CrudRepository<Customer, Long> {
//...
<T> T findById(long id, Class<T> type);
}
, getAddress() on the projection will be null, whereas getAddress() when fetching the entity type is populated correctly. Of these two unit tests, only testEntityWithOneToOne()will be successful:
#BeforeEach
void setUpData() {
customer = new Customer("first", "last");
Address address = new Address(customer, "street");
customer.setAddress(address);
entityManager.persist(address);
entityManager.persist(customer);
}
#Test
void testEntityWithOneToOne() {
Customer customerEntity = customers.findById(customer.getId().longValue());
assertThat(customerEntity.getAddress()).isNotNull();
}
#Test
void testProjectionWithOneToOne() {
CustomerProjection customerProjection = customers.findById(customer.getId(), CustomerProjection.class);
assertThat(customerProjection.getAddress()).isNotNull();
}
What's the problem here?
I have the following entity:
#Entity
public class SystemLogEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private long creationTime;
private String thread;
private int severity;
#Lob
private String message;
#ElementCollection(fetch = FetchType.EAGER)
#Lob
private List<String> stacktrace;
...
}
My Respository implements JpaSpecificationExecutor, which allows me to use Specifications to filter my db requests:
#Repository
public interface SystemLogRepository extends JpaRepository<SystemLogEntity, Long>, JpaSpecificationExecutor<SystemLogEntity> {
public List<SystemLogEntity> findAll(Specification spec);
}
For the simple field of the SystemLogEntity this works fine, the Predicate are straight forward.
Also if I filter for an exact item in a collection, the Predicate are still straight forward (in).
But how can I filter my SystemLogEntity after a stack trace collection item which is LIKE a given value?
In other words, I would e.g. like to filter SystemLogEntity after the term NullpointerException. Is this even possible with Predicate?
I hope this will work:
Specification<SystemLogEntity> stacktraceLike(String stacktrace) {
return (root, query, cb) -> cb.like(root.join("stacktrace"), "%" + stacktrace + "%");
}
More examples...
I'm using mongodb to store json documents, and since I'm using Hibernate ORM for my relational models I've decided to use the OGM for the mongo ones.
Currently all of my OGM entities share the same parent class, it looks something like:
#Entity
public abstract class Document {
private static final Gson GSON = new Gson();
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Type(type = "objectid")
protected String id;
public String id() {
return this.id;
}
#Override
public String toString() {
return Document.GSON.toJson(this);
}
}
#Entity
public class Address extends Document {
private String city;
private String street;
private int house;
}
#Entity
public class Person extends Document {
private String name;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private Set<Address> addresses;
}
(simplified of course)
What I expected that would happen when I persist a Person instance is that two collections will be created in the db, one for Person and the other for Address, which I inferred:
The various inheritance strategies are not supported by Hibernate OGM,
only the table per concrete class strategy is used
(Supported entity mapping - Hibernate OGM documentation)
But what happens in reality is that only one collection is created with the name Document with two documents in it:
{
_id : id1,
DTYPE : Person,
name : name of person
}
{
_id : id2,
DTYPE : Address,
city : City of address,
street : Street of address
house : 3
}
What am I missing?
Thanks
I think, it should be:
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Document {
...
}
I have an entity with has a field which represents composite primary key annotated with embeddeid and another field which is annotated with embedded annotation.
Both of these fields are not directly mapped with the the columns returned by the query passed to createNativeQuery method.
The getResultList returns me the list of entities, but the two fields which I mentioned are null in all the entities.
public interface Key{
public int hashCode()
}
#Embeddable
public class CompositePK impements Key{
private int empid;
private Date startdate;
private Date enddate;
}
#Embeddable
public class PartitionKey implements Key{
private String empname;
}
#Entity
public class Employee {
#EmbeddedId
private CompositePK id;
#Embedded
private PartitionKey name;
#Column(name="empid")
private int empid;
#Column(name="empname")
private String empname;
#Column(name="startdate")
private Date startdate;
#Column(name="enddate")
private Date enddate;
}
public class Loader{
private static EntityManager em;
public static void main(String [] args){
//code to instantiate em goes here
//...
//....
Query query = em.createNativeQuery("select empid,empname,startdate,enddate from employees", Employee.class );
List entities = query.getResultList();
//print the list
System.out.println(entities);
}
}
The outcome of this is that the entities are populated but their fieldsid and name which are emdedded fields are null. Can anyone please suggest how to populate these two fields?
Thanks
I am using Hibernate-search for searching data in my Jboss application. I have 3 JPA entity classes that all extend BaseEntity class and each are indexed by Lucene. For example:
#MappedSuperclass
public abstract class BaseEntity implements Serializable {
#Temporal(TemporalType.TIMESTAMP)
private Date created;
public abstract Long getId();
}
#Entity
#Table(name = "DVD")
public class Dvd extends BaseEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Field
private String title;
}
#Entity
#Table(name = "BOOK")
public class Book extends BaseEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Field
private String author;
}
Now I would like to search for either DVD title or Book author by wildcard search query and get the result list as List. This is what I have this far:
public List<BaseEntity> search(String query, int firstResult, int maxResults) {
List<BaseEntity> results = null;
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(em);
Query luceneQuery = new WildcardQuery(new Term("*", "*" + query + "*"));
FullTextQuery fullTextQuery = fullTextEntityManager.createFullTextQuery(luceneQuery, BaseEntity.class);
fullTextQuery.setFirstResult(firstResult);
fullTextQuery.setMaxResults(maxResults);
results = fullTextQuery.getResultList();
return results;
}
But with this I am not getting any results. How is it possible to get this to work or is there even way without using buildQueryBuilder for each entity? Thanks!
You'll want to use the varargs-style method for the classes, like so:
FullTextQuery fullTextQuery = fullTextEntityManager.createFullTextQuery(luceneQuery, DVD.class, Book.class);
This is because when Hibernate Search creates the search query, it adds the class name(s) to the query (for the _hibernate_class field, which is the indexed class' name).