I have a basic entity and I want to create a query that would retrieve this entity's members. Here is the entity:
public class TestEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String author;
#Column(insertable=false)
private String db_id;
}
And my test repository in which I try to create the query.
#Repository
#Transactional
public interface TestRepository extends JpaRepository<TestEntity, Long> {
#Query("INSERT INTO TestEntity VALUES (:object.id, :object.name :object.author)")
void insertSynchronizedColumns(TestEntity object);
}
This currently throws error:
antlr.MismatchedTokenException: expecting OPEN, found 'VALUES'
As a function argument I need the object and not the specific column names. Is there a way to retrieve object's id and other fields?
You can do it through nativeQuery as follows:
#Modifying
#Transactional
#Query("INSERT INTO TestEntity VALUES (:#{#object.id}, :#{#object.name}, :#{#object.author})",nativeQuery=true)
int insertSynchronizedColumns(#Param("object")TestEntity object);
I've got a UserRepository:
#Repository
public interface UserRepository extends JpaRepository<User, Long>
{
}
where User:
#Entity
#Table(name = 'user')
public class User
{
#Id
private Long id;
#OneToOne(mappedBy = "owner", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private UserDetails userDetails;
}
and UserDetails:
#Entity
#Table(name = 'user_details')
public class UserDetails
{
#Id
private Long id;
#OneToOne(fetch = FetchType.LAZY)
#MapsId
private User owner;
private String name;
}
Packages, imports, getters and setters are excluded for cleaner code.
Now, how can I find users by their name? Adding this to the UserRepository interface will not work:
List<User> findByName(String name);
because it throws:
No property name found for type User
I am looking for something like this:
List<User> findByNameOfUserDetails(String name);
Please take a look at the Spring Data JPA docs here.
You'll need something like findByUserDetailsName(String name).
To resolve this ambiguity you can use _ inside your method name to manually define traversal points. So our method name would be findByUserDetails_Name(String name).
Overview
I've got an #Entity with an #EmbeddedId composite key. The entities are exposed over a REST api which uses a BackendIdConverter to convert the id string back to an instance of the #Embeddable composite key. My understanding is that this is then used to identify an instance of the #Entity, but that isn't happening.
Question
How is the #Embeddable composite key resolved back to an #Entity?
Code
#Entity
public class MyEntity {
#EmbeddedId
private MyEntityIdentifier id;
#Embeddable
public class MyEntityIdentifier implements Serializable {
public static final String COMPOSITE_KEY_DELIMITER = "_#_";
#Column
private String idPartOne;
#Column
#Temporal(TemporalType.DATE)
private Date idPartTwo;
#Component
public class StringToMyEntityIdentifierConverter implements BackendIdConverter {
#Override
public Serializable fromRequestId(String id, Class<?> aClass) {
String[] split = id.split(COMPOSITE_KEY_DELIMITER);
String idPartOne = split[0];
Date idPartTwo = Date.valueOf(split[1]);
return new MyEntityIdentifier(fullName, lastUpdated);
}
public interface MyEntityRepository extends JpaRepository<MyEntity, MyEntityIdentifier> {
}
I have superclass:
#MappedSuperclass
public abstract class BaseEntity {
#Id #GeneratedValue
private Long id;
#Version
private long version;
}
and two subclasses:
#Entity
#Table(name = "\"user\"")
public class User extends BaseEntity {
private String username;
#org.hibernate.annotations.Type(type = "yes_no")
private boolean isAdmin;
// constructor/getters/setters etc.
}
#Entity
public class Product extends BaseEntity {
public String name;
public BigDecimal price;
// constructor/getters/setters etc.
}
I can query for all subclasses using code:
entityManager.unwrap(Session.class)
.createCriteria(BaseEntity.class)
.list()
.forEach(x -> System.out.println(x));
how I can get the same results via JPA (without unwrap, is it possible?). I tried using createQuery("from BaseEntity") but get BaseEntity not mapped exception.
EDIT: I know that this will result in two SELECT statement. And it must be MappedSuperclass - I would like to not change that.
I want to use one class to map three tables. I know javax.persistance provides the #SecondaryTable annotation to map two tables to one class.
Below is the code, where I have used #SecondaryTable. It allows me to define only one secondary table. But I need 3 tables to be used by the same class.
#Entity
#Table(name = "table1")
#SecondaryTable(name="table2")
public class TableConfig
implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#Column(name = "mac", table= "table1")
private String uniqueIdentifier;
I want to use one class to map three tables, From what I know is that javax.persistance provides #SecondaryTable annotation to map two tables to one class
use #SecondaryTables to map more than one table.
You can map a single entity bean to several tables using the #SecondaryTables class level annotations. To express that a column is in a particular table, use the table parameter of #Column or #JoinColumn.
for example there is 3 entity's namely: Name , Address & Student:
Name entity will look like:
#Entity
#Table(name="name")
public class Name implements Serializable {
#Id
#Column(name="id")
private int id;
#Column(name="name")
private String name;
public Name(){}
public Name(int id,String name){
this.id=id;
this.name=name;
}
//getters and setters
}
Address entity will look like:
#Entity
#Table(name="address")
public class Address implements Serializable {
#Id
#Column(name="id")
private int id;
#Column(name="address")
private String address;
public Address(){}
public Address(int id, String address) {
super();
this.id = id;
this.address = address;
}
//getters and setters
}
Student entity will look like:
#Entity
#Table(name="student")
#SecondaryTables({
#SecondaryTable(name="name", pkJoinColumns={
#PrimaryKeyJoinColumn(name="id", referencedColumnName="student_id") }),
#SecondaryTable(name="address", pkJoinColumns={
#PrimaryKeyJoinColumn(name="id", referencedColumnName="student_id") })
})
public class Student implements Serializable {
#Id
#Column(name="student_id")
private int studentId;
#Column(table="name")
private String name;
#Column(table="address")
private String address;
public Student(){}
public Student(int studentId){
this.studentId=studentId;
}
//getters and setters
}
Store like:
Student s= new Student(1);
session.save(s);
Name n=new Name(s.getStudentId(),"Bilal Hasan");
session.save(n);
Address address = new Address(s.getStudentId(), "India");
session.save(address);
Student ob = (Student)session.get(Student.class, s.getStudentId());
System.out.println(ob.getStudentId());
System.out.println(ob.getName());
System.out.println(ob.getAddress());
ouput:
1
Bilal Hasan
India
you can define one class like below :
#Entity
#Table(name="table1")
#SecondaryTables({
#SecondaryTable(name="table2", pkColumnJoins={#PrimaryKeyJoinColumn(name = "id")}),
#SecondaryTable(name="table3", pkColumnJoins={#PrimaryKeyJoinColumn(name = "id")})
})
public class TestEntity {
#Id
#GeneratedValue
private int id;
private String field1;
#Column(name="column2", table="table2")
private String field2;
#Column(name="column3", table="table3")
private String field3;
getter and setter...
}
In your DB, should has three table, and all of them should has the same primary key "id".
then, use can test like this:
TestEntity test = new TestEntity();
test.setField1("field1");
test.setField2("field2");
test.setField3("field3");
em.merge(test);
after test, in your DB, you will find one record in each table:
table1:
1, field1
table2:
1, field2
table3:
1, field3
all of them will share the primary key value. Hope this will help you.
In Hibernate mapping file you can specify the entity-name mapping with virtual name along with polymorphism="explicit" and class name would be physical class name. Like that you may do multiple mappings. While loading the object use entityname (virtual name).