Use save() method in Play! with inheritance (JPA) - java

I have my super abstract class :
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class User {
#Id
public int id;
public String name;
}
And two other classes extends User:
Customer
#Entity
#Table(name = "customers")
public class Customer extends User{
#Id
public int id;
public String role;
public Customer(String role){
super();
this.role = role;
}
}
Seller
#Entity
#Table(name = "sellers")
public class Seller extends User{
#Id
#GeneratedValue
public int id;
public String role; // Seller
public Seller(String role){
super();
this.role = role;
}
}
I would like to be able to use the save() method in play, so I wrote this :
public static Result saveCustomer(){
Customer customer = Form.form(Customer.class).bindFromRequest().get();
customer.save();
return ok();
}
But, save() is not defined.
What would be the way to solve this issue ?

Actually... to get the entityManager in play 2.x you hava a Helper.
JPA.em().persist(object);
you can see more information in this link.

save() method is a part of GenericModel which belongs to Play 1.x. Since, you use Play 2.x you should use JPA object and entityManager.persist() method.

Related

Query with composite PK collection via spring data (Hibernate JPA)

I have entity class User with composite key via #IdClass annotation
#Entity
#IdClass(UserId.class)
public class User {
#Id
private String name;
#Id
private String surname;
private boolean active;
}
Composite key:
#Data
public class UserId implements Serializable {
private String name;
private String surname;
}
I use Spring Data with hibernate JPA under hood. Therefore I have repo interface:
public interface UserRepo extends JpaRepository<User, UserId> {
}
And I'd like to get all active users from db by list of concrete names and surnames.
E.g. I'd like to use method like this
List<User> findAllByActiveTrue(List<UserId> ids);
How can I do query for this requirement via Spring Data or JPQL?
You can use #Embeddable & #EmbeddedId for composite primary key
#Embeddable
public class UserId implements Serializable {
private String name;
private String surname;
}
#Entity
public class User {
#EmbeddedId
private UserId userId;
...
}
Then query like
List<User> findByUserIdInAndActiveTrue(List<UserId> ids);
A good tutorial about #Embeddable & #EmbeddedId here

Custom AuditorAware getCurrentAuditor with #MappedSuperclass

I am attempting to load a customized value into the #CreatedBy field in my AuditFields entity. Whenever I make a POST request, I am expecting Spring Data Rest to use this AuditorAwareImpl and pass the TestPrincipal string to the #CreatedBy field.
The result I am actually getting is 409 Conflict, SQL Constraint created_by is null.
The BaseEntity needs to use #MappedSuperclass but I think it needs the functionality of #Entity in order to pass the value through to #CreatedBy?
Any pointers here would be greatly appreciated.
AuditEntity
#Embeddable
#Access(AccessType.FIELD)
#Data
#EntityListeners(AuditingEntityListener.class)
public class AuditFields implements Serializable {
#CreatedBy
#Column(name="CREATED_BY", length=256)
private String createdBy;
#Column(name="CREATED_TIMESTAMP")
private LocalDateTime createTimestamp = LocalDateTime.now();
...
...
}
BaseEntity
#MappedSuperclass
#Data
#JsonIgnoreProperties(ignoreUnknown = true)
public class BaseEntity implements Serializable {
#Column(name="RECORD_STATUS_CODE", length=1)
#EqualsAndHashCode.Exclude
private String myStatus;
#Version
#Column(name="VERSION_NUMBER")
#Setter(AccessLevel.PROTECTED)
#EqualsAndHashCode.Exclude
private Long versionNumber;
#Embedded
#EqualsAndHashCode.Exclude
private AuditEntity auditFields;
}
AuditorAwareImpl
#Configuration
#EnableJpaAuditing(auditorAwareRef = "auditorProvider")
public class AuditorAwareImpl {
#Bean
public AuditorAware<String> auditorProvider() {
return new AuditorAware<String>() {
#Override
public Optional<String> getCurrentAuditor() {
return Optional.of("TestPrincipal");
}
};
}
}
The trick here is that #CreatedBy doesn't work in an #Embedded entity without some extra work.
I pieced together a few different tutorials, the result being that I put the #EntityListener in my MyEntity and wrote a custom listener class that uses #PrePost. You can then build it out more by adding a BaseEntity that embeds the AuditEntity, etc.
AuditEntity
#Embeddable
#Data
public class AuditEntity {
#Column(name="CREATED_BY")
#CreatedBy
private String createdBy;
// additional fields ...
}
MyEntity
#Data
#Table(name="TABLENAME", schema="SCHEMANAME")
#EntityListeners(CustomAuditListener.class)
public class MyEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="MY_ID")
private Long myId;
#Embedded
#EqualsAndHashCode.Exclude
private AuditEntity auditFields;
}
CustomAuditListener
public class CustomAuditListener {
#PrePersist
public void prePersist(Object obj) {
MyEntity entity = (MyEntity) obj;
AuditFields audit = new AuditFields();
audit.setCreatedBy("CreatedByValueHere")
entity.setAuditFields(audit);
}
// can add #PreUpdate, etc, here
}

Hibernate MappedSuperclass via JPA

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.

QueryDSL query exception

I have a problem with a QueryDSL query. Classes:
#Entity
#Table(name="project")
#Cacheable(true)
#Cache(usage= CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Project extends DomainObject implements Comparable<Project>, IconizedComponent, Commentable {
#ManyToMany(targetEntity=Student.class)
#JoinTable(name="project_student")
#Sort(type=SortType.NATURAL) //Required by hibernate
#QueryInit({"user"})
private SortedSet<Student> projectParticipants = new TreeSet<Student>();
private Project(){}
//attributes, get+set methods etc
}
#Entity
#Cacheable(true)
#Cache(usage= CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) //Hibernate specific
public class Student extends Role {
public Student(){}
//attributes, get+set methods etc
}
#Entity
#DiscriminatorColumn(name = "rolename", discriminatorType = DiscriminatorType.STRING, length = 8)
#Table(name="role", uniqueConstraints={#UniqueConstraint(columnNames={"user_id","rolename"}, name = "role_is_unique")})
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public abstract class Role extends LazyDeletableDomainObject implements Comparable<Role> {
#ManyToOne(optional=false)
protected User user;
public Role(){}
//attributes, get+set methods etc
}
#Entity
#Table(name="user")
#Cacheable(true)
#Cache(usage= CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) //Hibernate specific
public class User extends LazyDeletableDomainObject implements Comparable<User>, IconizedComponent {
private String firstName;
private String lastName;
public User(){}
//attributes, get+set methods etc
}
Query:
private BooleanExpression authorsNameContains(String searchTerm){
QUser user = new QUser("user");
user.firstName.containsIgnoreCase(searchTerm).or(user.lastName.contains(searchTerm));
QStudent student = new QStudent("student");
student.user.eq(user);
return QProject.project.projectParticipants.contains(student);
//java.lang.IllegalArgumentException: Undeclared path 'student'. Add this path as a source to the query to be able to reference it.
}
I have also tried annotating the projectParticipants set in Project with
#QueryInit("*.*")
But that gives the same exception. Any hints?
#Timo Westkämper
#siebZ0r
Thanks for your attention. Sorry for the delayed reply and incorrectly phrased question. Actually what I wanted to do was to write a working BooleanExpression.
In combination with the annotations already made, this was what I was after:
private BooleanExpression authorsFirstNameContains(String searchTerm){
return QProject.project.projectParticipants.any().user.firstName.containsIgnoreCase(searchTerm);
}
I got this right with the help of a colleague.

How to work with interfaces and JPA

I should start out by saying that I am fairly new to Java EE and that I do not have a strong theoretical background in Java yet.
I'm having trouble grasping how to use JPA together with interfaces in Java. To illustrate what I find hard I created a very simple example.
If I have two simple interfaces Person and Pet:
public interface Person
{
public Pet getPet();
public void setPet(Pet pet);
}
public interface Pet
{
public String getName();
}
And an Entity PersonEntity which implements Person as well as a PetEntity which implements Pet:
#Entity
public class PersonEntity implements Person
{
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private PetEntity pet;
#Override
public void setPet(Pet pet)
{
/* How do i solve this? */
}
}
#Entity
public class PetEntity implements Pet
{
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String name;
/* Getters and Setters omitted */
}
How do I properly handle the case in the setPet method in which I want to persist the relationships between the two entities above?
The main reason I want to use interfaces is because I want to keep dependencies between modules/layers to the public interfaces. How else do I avoid getting a dependency from e.g. my ManagedBean directly to an Entity?
If someone recommends against using interfaces on entities, then please explain what alternatives methods or patterns there are.
You can use targetEntity property in the relationship annotation.
#Entity
public class PersonEntity implements Person {
private Long id;
private Pet pet;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#Override
#OneToOne(targetEntity = PetEntity.class)
public Pet getPet() {
return pet;
}
public void setPet(Pet pet) {
this.pet = pet;
}
}

Categories

Resources